GoHighLevel Forms & Surveys 2025: UTM, Consent, Attribution

by

GoHighLevel forms and surveys 2025: UTM tracking, consent-first SMS/email, and clean attribution setup
Capture UTMs, gate consent, and attribute wins correctly with GoHighLevel forms and surveys.

Forms and surveys are where revenue starts—and where data often breaks. In 2025, winning funnels on GoHighLevel require three things: persistent UTM tracking, consent-first messaging (email/SMS), and clean attribution into contacts and opportunities. This step-by-step guide gives you the exact fields, scripts, and copy to deploy a compliant, reliable setup that your sales and analytics teams can trust.

Need a fast WordPress stack for GHL embeds? See Best WordPress Themes for GoHighLevel (2025). Evaluating platforms? Compare GoHighLevel vs Salesforce. Run your funnel on the go with the GoHighLevel Mobile App Guide.

Try GoHighLevel — pipelines, calendars, forms/surveys, and automations in one stack. Host fast on Hostinger, register domains via Namecheap, and source templates from Envato. Discover deals on AppSumo.


GoHighLevel Forms & Surveys: UTM + Consent Setup

This configuration ensures that every lead captured through GoHighLevel (GHL) forms or surveys includes consent status and attribution metadata (first touch and last touch UTMs, click IDs, referrer, and landing page) so you can measure true source-to-revenue impact.

  • Primary goal: Persist UTMs and identifiers across pages and write them into GHL contact/opportunity fields on submit.
  • Compliance goal: Gate SMS/email by explicit consent, handle STOP/HELP, and respect quiet hours.
  • Attribution goal: Store both first-touch and last-touch values with a 90-day lookback for channel comparison.

Architecture: Where UTMs Live and How to Persist Them

Capture on the first landing page, persist during navigation, and submit to GHL with the form.

  1. Create custom fields in GHL (Contacts):
    • utm_source_first, utm_medium_first, utm_campaign_first, utm_term_first, utm_content_first
    • utm_source_last, utm_medium_last, utm_campaign_last, utm_term_last, utm_content_last
    • gclid_last, fbclid_last
    • referrer_first, referrer_last
    • landing_page_first, landing_page_last
    • sms_consent (boolean), email_consent (boolean), consent_timestamp, consent_ip
  2. Persist UTMs on the site (WordPress example): Parse query parameters and store in localStorage with a 90-day TTL. Keep a separate namespace for first-touch values that never overwrite once set.
    <script>
    (function(){
      var qs = new URLSearchParams(window.location.search);
      var now = Date.now();
      var TTL = 90*24*60*60*1000; // 90 days
      function setIfEmpty(key, val){
        if(!localStorage.getItem(key) && val){ localStorage.setItem(key, val); }
      }
      function setWithTTL(key, val){
        if(!val) return;
        localStorage.setItem(key, JSON.stringify({v: val, t: now}));
      }
      function getWithTTL(key){
        var raw = localStorage.getItem(key); if(!raw) return null;
        try{ var obj = JSON.parse(raw); if(now - obj.t < TTL) return obj.v; }catch(e){}
        localStorage.removeItem(key); return null;
      }
      var params = ["utm_source","utm_medium","utm_campaign","utm_term","utm_content","gclid","fbclid"]; 
      var ref = document.referrer || "";
      var land = window.location.href;
      // First touch - set once
      params.forEach(function(p){ var v = qs.get(p); if(v){ setIfEmpty("ft_"+p, v); } });
      if(ref) setIfEmpty("ft_referrer", ref);
      setIfEmpty("ft_landing", land);
      // Last touch - refresh
      params.forEach(function(p){ var v = qs.get(p); if(v){ setWithTTL("lt_"+p, v); } });
      if(ref) setWithTTL("lt_referrer", ref);
      setWithTTL("lt_landing", land);
      // Expose helper for forms
      window.__utm = {
        ft: function(p){ return localStorage.getItem("ft_"+p) || ""; },
        lt: function(p){ return getWithTTL("lt_"+p) || ""; },
        refFirst: function(){ return localStorage.getItem("ft_referrer") || ""; },
        refLast: function(){ return getWithTTL("lt_referrer") || ""; },
        landFirst: function(){ return localStorage.getItem("ft_landing") || ""; },
        landLast: function(){ return getWithTTL("lt_landing") || ""; }
      };
    })();
    </script>
  3. Write values into GHL form fields: On pages with GHL embeds, map hidden inputs to your custom fields. Reserve iframe height to avoid CLS.
    <style> .ghl-embed { min-height: 900px; } @media(max-width:640px){ .ghl-embed{ min-height: 1080px; } } </style>
    <script>
      document.addEventListener('DOMContentLoaded', function(){
        function fillHidden(){
          var map = {
            'utm_source_first': window.__utm.ft('utm_source'),
            'utm_medium_first': window.__utm.ft('utm_medium'),
            'utm_campaign_first': window.__utm.ft('utm_campaign'),
            'utm_term_first': window.__utm.ft('utm_term'),
            'utm_content_first': window.__utm.ft('utm_content'),
            'utm_source_last': window.__utm.lt('utm_source'),
            'utm_medium_last': window.__utm.lt('utm_medium'),
            'utm_campaign_last': window.__utm.lt('utm_campaign'),
            'utm_term_last': window.__utm.lt('utm_term'),
            'utm_content_last': window.__utm.lt('utm_content'),
            'gclid_last': window.__utm.lt('gclid'),
            'fbclid_last': window.__utm.lt('fbclid'),
            'referrer_first': window.__utm.refFirst(),
            'referrer_last': window.__utm.refLast(),
            'landing_page_first': window.__utm.landFirst(),
            'landing_page_last': window.__utm.landLast()
          };
          Object.keys(map).forEach(function(name){
            var el = document.querySelector('[name="'+name+'"]');
            if(el && map[name]) el.value = map[name];
          });
        }
        // Call once; if your GHL form loads late, call again on load event for the iframe.
        fillHidden();
      });
    </script>

    Tip: Use Header Footer Code Manager or Perfmatters to load these snippets only on landing/thank-you pages.


Consent-First Messaging: Fields, Copy, and Enforcement

Gate outbound messaging by explicit consent. Do not pre-check boxes. Store time and IP when consent is granted.

  • Create consent fields: sms_consent (boolean), email_consent (boolean), consent_timestamp, consent_ip.
  • Add checkboxes to forms:
    <label>
      <input type="checkbox" name="sms_consent" value="true" />
      I agree to receive SMS from {Brand}. Msg & data rates may apply. Reply STOP to opt out, HELP for help.
    </label>
    <label>
      <input type="checkbox" name="email_consent" value="true" />
      I agree to receive emails from {Brand}. You can unsubscribe anytime.
    </label>
    <input type="hidden" name="consent_timestamp" />
    <input type="hidden" name="consent_ip" />
    <script>
      document.addEventListener('submit', function(e){
        var ts = new Date().toISOString();
        var ipEl = document.querySelector('[name="consent_ip"]');
        var tsEl = document.querySelector('[name="consent_timestamp"]');
        if(tsEl) tsEl.value = ts;
        // Optionally set IP via server or a trusted edge function; avoid public IP APIs if not compliant with your policy.
      }, true);
    </script>
  • Workflows: In GHL, route SMS/email sequences only if sms_consent=true or email_consent=true. Enforce quiet hours by contact timezone.
  • Inbox rules: Make STOP/HELP handling explicit and log status changes.

Attribution Strategy: First Touch vs Last Touch

Store both views for analysis. Use a 90-day TTL for last-touch fields and never overwrite first-touch once set.

  • First touch: Initial UTMs, referrer, and landing page when contact is first created.
  • Last touch: Most recent UTMs, referrer, and landing page at the time of form submit or booking.
  • Reporting: Build dashboards for Bookings/Wins by first-touch and last-touch. Use Looker Studio/GA4 connectors as needed.

Implementation Guide: Step-by-Step

  1. Define your data dictionary: Names, types, and descriptions for all UTM and consent fields.
  2. Create GHL custom fields: As listed above for contacts (and map to opportunities if used).
  3. Update forms/surveys: Add consent checkboxes and hidden UTM fields with the exact GHL field names.
  4. Deploy scripts on site: Add UTM persistence and hidden-field fill scripts to landing pages only.
  5. Protect CWV: Reserve iframe height and keep themes/plugins lean. See WordPress setup.
  6. Scope messaging: In workflows, gate branches by sms_consent/email_consent and enforce quiet hours.
  7. QA end-to-end: Submit test leads with UTMs; verify field population, consent flags, and attribution in GHL records.
  8. Thank-you page tracking: Fire conversions only on TY pages to keep attribution clean.
  9. Train the team: How to respect DND, update stages, and read attribution fields.
  10. Monitor 14 days: Check fill rates, consent rates, and booking/show/win rates by channel.

Expert Insights & Pitfalls

  • Do not pre-check consent boxes. Explicit opt-in only.
  • Handle ITP and private browsing: Store UTMs in localStorage and pass on the next submit; avoid long-lived third-party cookies.
  • Cross-domain journeys: If ads land on a microsite, propagate UTMs via URL params into your main domain.
  • Duplicate contacts: Use dedupe rules (email/phone) and a one-active-opportunity policy per pipeline.
  • Ad blockers: Client-side only setups are fragile; validate server-side events if critical.

Alternatives & Enhancements

  • GTM Server-Side: Improves data resilience; still write UTMs to GHL fields for CRM truth.
  • Direct API: For complex forms, post to GHL API with payload including UTM/consent fields from your backend.
  • Middleware (n8n/Make/Zapier): Normalize UTMs and enforce field mappings between websites and GHL.

Final Recommendations

  • Persist UTMs and submit both first-touch and last-touch to GHL.
  • Gate messaging by consent and log timestamp/IP.
  • Load embeds cleanly with reserved height and page-scoped scripts.
  • Report by channel using both FT and LT views; optimize for speed-to-lead and show rate first.

Launch on GoHighLevel — host fast on Hostinger, secure domains with Namecheap, and grab templates on Envato. Explore tool deals via AppSumo.


Frequently Asked Questions

Which UTMs should I capture for GoHighLevel?

Capture source, medium, campaign, term, content plus gclid/fbclid, referrer, and landing page for both first-touch and last-touch.

How long should I store last-touch values?

Use a 90-day TTL to align with common attribution windows while avoiding stale data.

Can I pre-check consent boxes for SMS/email?

No. Use explicit opt-in with unchecked boxes to meet best-practice and regulatory expectations.

How do I keep PageSpeed high with embeds?

Reserve iframe height, compress images, and load scripts only on landing/booking pages. See our WordPress performance guide.

Where do I store UTMs in GHL?

Create contact custom fields matching your naming scheme (e.g., utm_source_first, utm_source_last) and map hidden inputs to them.

How do I enforce quiet hours?

In workflows, check the contact’s timezone and send only inside your allowed window; queue outside.

What’s the right decision point for attribution?

Record UTMs at form submit and optionally update at booking. Fire conversions on thank-you pages only.

Can I do this without code?

Mostly, yes. Use native hidden fields in GHL and a lightweight UTM script. For advanced cases, add GTM or server-side enrichment.

How do I avoid duplicate deals?

Enforce a one-active-opportunity rule per pipeline and prevent auto-creation if an open deal exists.

What if users arrive via a microsite?

Propagate UTMs through your redirect links and ensure your main domain reads and stores them on arrival.


Recommended resources

  • GoHighLevel — pipelines, calendars, forms/surveys, automations.
  • Hostinger — fast WordPress hosting for clean embeds.
  • Namecheap — domains & DNS for branded funnels.
  • Envato — lightweight landing templates & design assets.
  • AppSumo — discover complementary tools and lifetime deals.

Disclosure: Some links are affiliate links. If you purchase through them, we may earn a commission at no extra cost to you.

all_in_one_marketing_tool