GoHighLevel and WordPress: How to Track Lead Source Through to Your CRM

GoHighLevel and WordPress: The Attribution Gap

GoHighLevel (GHL) has become one of the most popular all-in-one platforms for agencies and service businesses. It combines CRM, pipeline management, email marketing, SMS, landing pages, and booking into a single platform — and many businesses run it alongside a WordPress website for their main web presence.

The problem: when leads come in through your WordPress forms or landing pages and land in GoHighLevel, the source data often doesn’t come with them. You see a new contact in your GHL CRM, but you don’t know if they came from a Google Ad, a Facebook campaign, an organic blog post, or a referral. That blind spot makes it impossible to evaluate which marketing is actually working.

This guide covers how to capture UTM parameters and lead source data from your WordPress site and pass it through to GoHighLevel contacts automatically.

Why Lead Source Data Matters in GoHighLevel

GoHighLevel is built around pipelines and contact management. When every contact has source data attached, you can:

  • See which ad campaigns are filling your pipeline — not just generating website clicks, but producing real CRM contacts and booked appointments
  • Filter pipeline deals by source — understand whether Google Ads leads close at a higher rate than Facebook leads, which is often true for service businesses
  • Trigger source-specific automations — send a different nurture sequence to a Google search lead vs. a Facebook ad lead vs. an organic visitor
  • Report accurate ROI to clients — if you use GHL to manage client funnels, source data lets you show exactly which campaigns are driving pipeline

How Lead Source Tracking Works With WordPress and GoHighLevel

The technical flow is the same regardless of which CRM or platform you’re connecting to:

  1. A visitor arrives on your WordPress site from a tagged URL (one with UTM parameters: utm_source, utm_medium, utm_campaign, etc.)
  2. A script on your site captures those UTM values and stores them in a first-party cookie so they persist as the visitor navigates between pages
  3. When the visitor submits a form, hidden fields in that form are populated with the stored UTM values
  4. The form submission — including the UTM data — gets sent to GoHighLevel, either through a native integration, Zapier, or a webhook
  5. GoHighLevel creates or updates the contact with the source data attached as custom fields

Step 1: Make Sure Your Campaigns Are UTM-Tagged

Before any tracking can happen, your traffic sources need to be tagged. A tagged URL carries UTM parameters that tell your tracking system where the visitor came from:

https://yoursite.com/service/?utm_source=google&utm_medium=cpc&utm_campaign=spring-special&utm_content=search-ad-v1

Tag every paid ad, every email campaign link, and every social post you control. Organic search traffic doesn’t need manual UTM tags — you’ll track that separately via Google Search Console. Direct traffic (visitors who type your URL) won’t have UTM data, which is expected.

Step 2: Capture UTMs in a Cookie on Landing

UTM parameters only exist in the URL on the first pageview. Once a visitor clicks to another page, they disappear from the address bar. You need a script that reads them on landing and writes them to a first-party cookie that persists across the session:

document.addEventListener('DOMContentLoaded', function() {
  const params = new URLSearchParams(window.location.search);
  const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
  
  utmParams.forEach(function(param) {
    const val = params.get(param);
    if (val) {
      document.cookie = param + '=' + encodeURIComponent(val)
        + '; path=/; max-age=7776000; SameSite=Lax';
    }
  });
  
  // Capture the landing page URL (only set on first visit)
  if (!readCookie('landing_page')) {
    document.cookie = 'landing_page=' + encodeURIComponent(window.location.href)
      + '; path=/; max-age=7776000; SameSite=Lax';
  }
});

function readCookie(name) {
  const m = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
  return m ? decodeURIComponent(m[2]) : '';
}

Add this script to your WordPress site via a plugin (like WPCode) or directly in your theme’s header. It runs on every page load and writes UTM values to cookies with a 90-day expiry.

Step 3: Create Custom Fields in GoHighLevel

GoHighLevel supports custom contact fields where you’ll store the source data. In your GHL account, go to Settings > Custom Fields > Contacts and add the following text fields:

  • Lead Source — maps from utm_source
  • Lead Medium — maps from utm_medium
  • Lead Campaign — maps from utm_campaign
  • Lead Content — maps from utm_content
  • Lead Keyword — maps from utm_term
  • Landing Page — maps from the landing page URL

Note the field keys that GHL assigns to each — you’ll need these when you configure the integration.

Step 4: Pass UTMs Through Your WordPress Forms to GoHighLevel

Now you need to connect your WordPress contact forms to GoHighLevel with the UTM data included. There are several common paths depending on your setup:

Option A: WordPress form plugin with a native GHL integration. Some form plugins (like WPForms with its CRM addons, or Fluent Forms) have native GoHighLevel integrations. Add hidden fields to your form for each UTM value, populate them with JavaScript from cookies on page load, and map them to the corresponding GHL custom fields in the integration settings.

Option B: GoHighLevel’s WordPress plugin. GHL offers a plugin that lets you embed GHL forms directly on your WordPress site. Add hidden fields to the GHL form and populate them with the UTM cookie values via JavaScript. The form submits directly to GHL, and the hidden fields land as contact data.

Option C: Webhook or Zapier. If your WordPress form plugin (Gravity Forms, Contact Form 7, WPForms) doesn’t have a native GHL integration, send the form data to a webhook and route it to GHL via Zapier or Make.com. Include the hidden UTM fields in the webhook payload and map them to GHL custom fields in your Zap.

Regardless of which path you use, the JavaScript to populate hidden UTM fields from cookies is the same:

document.addEventListener('DOMContentLoaded', function() {
  const fieldMap = {
    'lead_source_field': 'utm_source',
    'lead_medium_field': 'utm_medium',
    'lead_campaign_field': 'utm_campaign',
    'lead_content_field': 'utm_content',
    'lead_keyword_field': 'utm_term',
    'landing_page_field': 'landing_page'
  };
  
  Object.entries(fieldMap).forEach(function([fieldName, cookieName]) {
    const val = readCookie(cookieName);
    if (val) {
      const input = document.querySelector('[name="' + fieldName + '"]');
      if (input) input.value = val;
    }
  });
});

Replace the field names in fieldMap with the actual input field names or IDs in your form.

Step 5: Test End to End

Run a complete test before you trust the data in your GHL CRM:

  1. Open a private browser window and visit a tagged URL: yoursite.com/?utm_source=test&utm_medium=cpc&utm_campaign=tracking-test
  2. Navigate to another page on your site — confirm the cookies persist (check in DevTools > Application > Cookies)
  3. Submit your contact form with a test email address
  4. In GoHighLevel, find the new contact and check their custom fields — Lead Source should show “test”, Lead Medium should show “cpc”, Lead Campaign should show “tracking-test”

If the fields are empty, work backwards: Are the cookies being written? Are the hidden fields being populated by JavaScript? Is the integration mapping the fields correctly to the GHL custom fields?

Using Source Data in GoHighLevel Automations and Pipelines

Once data flows, put it to work:

Source-based workflow triggers: GHL’s automation workflows support conditions on contact fields. Create a branch that sends a different nurture sequence based on Lead Source. A contact from “google” who searched for your exact service is in a different mindset than one from “facebook” who saw your ad in their feed.

Pipeline filtering by source: Add Lead Source as a visible column in your pipeline views. You can quickly see whether one source is dominating at the top of the funnel, or whether a source that looks busy is actually converting to closed deals at a low rate.

Attribution reporting: With source data on every contact, you can build simple reports in GHL or export contacts and analyze in a spreadsheet. Track new contacts by source over time, deal close rates by source, and revenue by source if you’re logging deal values.

Opportunity tagging: When a contact converts to an Opportunity in GHL, the custom fields carry over. Tag opportunities by source to track which campaigns are generating pipeline, not just leads.

The Simpler Path: One Plugin Setup

The setup above works, but it involves custom JavaScript, per-form configuration, and ongoing maintenance whenever you change forms or update your site. Each new form or landing page requires the hidden fields and cookie-reading script to be wired up.

A dedicated WordPress attribution plugin removes that overhead. Sales Provenance installs once, captures UTM data automatically on every landing, and passes it to GoHighLevel (and other platforms) through every form on your site — no per-form JavaScript, no custom field mapping for each new form, and more data than basic UTM tracking alone (including first-click vs. last-click source and full session data).

If getting clean lead source data into your GoHighLevel CRM is something you want working this week, Sales Provenance is the fastest way to do it.