HubSpot is one of the most common CRMs for businesses running WordPress sites. The combination makes sense: HubSpot handles contacts, deals, and pipelines, and WordPress handles the website where leads come from. The problem is that connecting them so that lead source data actually survives the handoff takes more than installing the HubSpot plugin and calling it done.
This guide covers how to wire HubSpot and WordPress so that every contact in your CRM carries the channel, campaign, and keyword that drove the original visit — and how to use that data to answer which marketing actually produces customers.
What the HubSpot WordPress Plugin Does and What It Doesn’t
The official HubSpot WordPress plugin installs tracking code, connects HubSpot forms to WordPress, and syncs contact submissions to your CRM. For basic form-to-CRM flow, it works. For attribution, it falls short in two important ways.
First, HubSpot’s tracking code captures session data that HubSpot’s own analytics uses to populate the “Original source” and “Latest source” properties on contact records. This works reasonably well for traffic that arrives with clear referrer signals (organic search, paid ads with auto-tagging, social). It works poorly for direct traffic, offline sources, and campaigns that rely on UTM parameters rather than HubSpot’s native tracking.
Second, HubSpot’s native source tracking does not capture UTM parameters into custom contact properties unless you explicitly map them. A contact who arrived through a Google Ads campaign shows up as “Paid search” in HubSpot’s original source field — but the specific campaign, ad group, and keyword that drove the click are not stored anywhere you can filter or report on them without additional setup.
The gap: you can see broad channel attribution in HubSpot, but you cannot answer “which campaign produced our best leads” or “what keyword drove our highest-close-rate contacts” without custom field setup and UTM capture in your WordPress forms.
Setting Up UTM Capture in WordPress
The foundation of reliable HubSpot attribution is capturing UTM parameters when a visitor lands and passing them into the HubSpot contact record at form submission. The process:
- Capture UTM parameters from the URL on landing and store them in first-party cookies. A small script runs when any page loads, reads utm_source, utm_medium, utm_campaign, utm_term, and utm_content from the URL if present, and writes them to cookies with a 30-day expiration. The cookies persist as the visitor browses through multiple pages, so a visitor who lands on a blog post and later submits a contact form on your services page carries the original UTM data to the form.
- Add hidden fields to your HubSpot forms that read cookie values at submission. For each UTM parameter you want to capture, add a hidden field to the form in the HubSpot form editor. A small script reads the cookie values and populates the hidden fields when the form loads. When the visitor submits, the UTM values submit alongside their name and email.
- Map the hidden form fields to custom contact properties in HubSpot. In HubSpot, create custom contact properties for each UTM field (Lead Source Campaign, Lead Source Medium, Lead Source Term, etc.) and map the hidden form fields to these properties in the HubSpot form settings. When the form submits, HubSpot populates these properties on the contact record.
The result: every contact created through a HubSpot form on your WordPress site carries the full UTM data from the session that produced the lead, stored in searchable, filterable properties you can use in lists, reports, and workflows.
Custom HubSpot Contact Properties to Create
Before building the form and cookie setup, create these properties in HubSpot under Contacts > Properties:
- Lead Source Campaign (text) — maps from utm_campaign. Identifies the specific campaign that drove the visit.
- Lead Source Medium (text) — maps from utm_medium. Identifies the channel type (cpc, organic, email, social).
- Lead Source Term (text) — maps from utm_term. Captures the keyword for paid search campaigns.
- Lead Source Content (text) — maps from utm_content. Captures ad variation identifiers for A/B testing.
- Landing Page (text) — the first URL the contact visited. Captured from the cookie, not the form submission page.
- gclid (text) — Google click identifier, required for offline conversion upload to Google Ads. Captured the same way as UTM parameters.
- fbclid (text) — Facebook click identifier for Meta offline conversion upload.
Mark these properties as visible in the contact record so sales can see them without digging into property settings. Add them to the default contact view for your sales team.
The HubSpot Forms vs. Non-HubSpot Forms Decision
If your WordPress site uses HubSpot’s own forms (embedded via the plugin or the HubSpot tracking code), the hidden field approach works directly in the HubSpot form editor. Map the fields to your custom properties and the data flows automatically.
If your site uses WordPress form plugins (Gravity Forms, WPForms, Contact Form 7, Fluent Forms), you have two options for getting submissions into HubSpot:
- Native HubSpot integrations: Gravity Forms and Fluent Forms have native HubSpot add-ons that map form fields to HubSpot contact properties directly. Setup takes 15-20 minutes and does not require Zapier. Add hidden fields to the WordPress form, map them to your custom HubSpot properties, and submissions land directly in HubSpot with attribution data.
- Webhook to HubSpot API: Most WordPress form plugins support webhooks. Send the form submission directly to HubSpot’s Contacts API endpoint with a POST request, mapping your form fields to HubSpot property names in the request body. No middleware, no Zapier, lower latency, and one fewer dependency in the stack.
If you are building from scratch, HubSpot’s native forms are the simplest path — the integration is first-party and maintained. If your site already uses a WordPress form plugin with a large amount of conditional logic or custom styling, native integration via Gravity Forms or Fluent Forms is cleaner than switching to HubSpot forms.
First-Touch vs. Latest-Touch in HubSpot
HubSpot automatically tracks “Original source” (first touch) and “Latest source” (most recent touch) as built-in properties. When you add custom UTM capture, you create a third layer: the UTM data from the specific session that produced the form submission, which may be a middle-touch interaction.
How to use each:
- Original source (HubSpot native): shows the channel that first introduced the contact to your site. Useful for understanding which channels generate new awareness.
- Custom UTM properties (from form submission): shows the channel and campaign that prompted the contact to take action. Useful for understanding what drove the conversion event specifically.
- Offline conversion data from closed deals: the most valuable layer, described below.
For most lead generation businesses, the custom UTM properties on the contact record are the most actionable for campaign optimization, because they tie directly to the touch that produced the lead. HubSpot’s native original source is useful context, but a contact who was introduced by organic search and converted four months later through a Google Ads click shows organic as the original source — which undercredits paid and overcredits organic if you optimize based on original source alone.
HubSpot Deals and Attribution Reporting
Contact-level attribution tells you which channels produce leads. Deal-level attribution tells you which channels produce customers. The gap between these two numbers — conversion rate from lead to closed deal by source — is the most useful data in your marketing stack.
To build this report in HubSpot:
- Ensure attribution properties are on the deal, not just the contact. In HubSpot, when a deal is created from a contact, the deal does not automatically inherit the contact’s custom properties. Create the same UTM properties on the Deal object (or use HubSpot’s association to pull contact properties into deal reports).
- Use HubSpot’s Custom Report Builder. Build a contacts-to-deals report that groups closed deals by Lead Source Campaign or Lead Source Medium and calculates deal count, total deal value, and conversion rate. This shows which campaigns produce the most closed revenue, not just the most leads.
- Segment by deal stage for pipeline view. A pipeline report broken down by lead source shows where each source’s leads are getting stuck — high lead volume from a source that consistently stalls at proposal stage is a different problem than low volume from a source that closes at high rates.
Offline Conversion Upload from HubSpot to Google Ads
If your WordPress forms capture gclid (Google Ads click identifier) into a custom HubSpot property, you have everything you need to close the attribution loop with Google Ads. When a deal closes in HubSpot, you can upload it as an offline conversion to Google Ads, which tells Google’s bidding algorithm to optimize toward the keywords and campaigns that produced actual revenue, not just form submissions.
Two ways to do this from HubSpot:
- HubSpot’s native Google Ads integration: HubSpot Pro and Enterprise include a Google Ads integration that can sync deal activity back to Google Ads as offline conversions. Requires connecting your Google Ads account in HubSpot’s marketing integrations settings. When a deal reaches a target stage, HubSpot sends the conversion event to Google Ads automatically.
- Manual CSV upload or Zapier workflow: For businesses on HubSpot Starter, export closed deals with gclid and conversion date from HubSpot and upload the CSV directly to Google Ads under Conversions > Offline conversion imports. Or trigger a Zapier workflow when a deal closes that formats and sends the conversion to the Google Ads API.
The same principle applies to Meta Ads: if you capture fbclid on form submission and store it in a HubSpot property, you can upload closed deals as offline events to Meta via the Conversions API, improving Meta’s delivery optimization toward your best-converting audience segments.
What a Complete HubSpot + WordPress Attribution Stack Looks Like
When the stack is fully wired:
- A visitor clicks a Google Ad for keyword “marketing agency Madison” and lands on your WordPress site
- The UTM capture script reads utm_source=google, utm_medium=cpc, utm_campaign=branded-search, utm_term=marketing agency madison, and gclid from the URL and stores them in cookies
- The visitor browses three pages and submits your contact form
- The form hidden fields read the cookie values and submit them alongside the contact’s name and email
- HubSpot creates a contact with Lead Source Medium=cpc, Lead Source Campaign=branded-search, Lead Source Term=marketing agency madison, gclid=[value]
- Sales works the deal over six weeks and closes it
- The closed deal revenue is uploaded back to Google Ads as an offline conversion tied to the original gclid
- Google Ads begins optimizing bid strategy toward the keyword patterns that produce closed clients, not just form fills
Every component of this is possible without custom development, using HubSpot’s native tools, standard WordPress form plugins, and a small JavaScript snippet for UTM capture. The setup takes a few hours; the payoff is that every marketing decision is based on what actually produces revenue.
For a WordPress plugin that handles UTM capture, hidden field population, HubSpot routing, and Google Ads offline conversion upload as an integrated layer — without building each component separately — Sales Provenance connects every piece described here. Related reading: UTM parameter tracking on WordPress, CRM integration for WordPress, Google Ads conversion tracking for WordPress, and closed-loop reporting for WordPress.