Blog

  • Salesforce and WordPress Lead Tracking: Getting Attribution Data Into Your CRM

    Salesforce is the dominant CRM for companies with active sales teams, and WordPress is the most common platform for the websites those sales teams rely on for leads. The combination is everywhere — but the default setup leaves a critical gap. Leads flow into Salesforce through Web-to-Lead forms or integration tools, contact records appear in the pipeline, and sales reps start working them. What is usually missing is where those leads came from. The source fields are blank, or they show “Web” as a catch-all with no campaign detail, and there is no reliable way to connect a closed deal back to the channel or ad that generated it.

    This guide covers how to wire Salesforce and WordPress together so that every lead in your CRM carries the full attribution trail from the session that produced it.

    What Salesforce Tracks by Default

    Salesforce has a built-in Lead Source field, but it is a manually set dropdown — not an automatically captured value. When a Web-to-Lead form submits, Salesforce creates a lead record with whatever fields you included in the form. If you did not include UTM data, the lead has no UTM data. The Lead Source field will typically show whatever default value your admin configured, usually “Web” or blank.

    Salesforce does not have a native mechanism to read UTM parameters from the visitor’s landing URL and carry them into the lead record. That requires a UTM capture layer on your WordPress site and custom fields on the Salesforce Lead object to receive the data.

    Setting Up UTM Capture in WordPress

    The foundation is capturing UTM parameters when a visitor first arrives on your site and persisting them across page navigation so they are available when the visitor eventually submits a form. The pattern is the same regardless of which CRM you are feeding:

    1. On landing, read UTM parameters from the URL and write them to first-party cookies. A small JavaScript snippet checks the URL for utm_source, utm_medium, utm_campaign, utm_term, and utm_content. When any are present, it writes them to cookies with a 30-day expiration. The cookies survive page navigation — a visitor who lands on a blog post, browses to a services page, and submits a contact form three clicks later still carries the UTMs from their original landing URL.
    2. Also capture the gclid (Google click identifier) and fbclid (Facebook click identifier) using the same cookie approach. These click identifiers are what you need later for Google Ads offline conversion upload — they tie the closed deal in Salesforce back to the specific paid click that started the journey.
    3. Capture the first landing page URL in a separate cookie (set only if the cookie does not already exist). This gives you the entry point the visitor used, which is valuable context alongside the UTMs for understanding which content is generating quality leads.

    Custom Fields to Create in Salesforce

    Before updating your forms, create custom fields in Salesforce to hold the attribution data. In Salesforce Setup, go to Object Manager > Lead > Fields and Relationships and add these as custom Text fields:

    • UTM Source (Text, 255) — maps from utm_source (google, facebook, linkedin, email, etc.)
    • UTM Medium (Text, 255) — maps from utm_medium (cpc, organic, email, social, etc.)
    • UTM Campaign (Text, 255) — maps from utm_campaign (the campaign name you set in your ad platform)
    • UTM Term (Text, 255) — maps from utm_term (the keyword for paid search)
    • UTM Content (Text, 255) — maps from utm_content (ad variation identifier for A/B testing)
    • Landing Page (URL, 255) — the first page the visitor landed on
    • GCLID (Text, 255) — Google click identifier, required for Google Ads offline conversion upload
    • FBCLID (Text, 255) — Facebook click identifier, for Meta offline conversion upload

    Mirror these same fields on the Opportunity object. When a Lead converts to an Opportunity in Salesforce, the standard conversion does not automatically carry custom fields — you need a Flow or Process Builder automation to copy them, which is covered below.

    Connecting WordPress Forms to Salesforce

    There are three main approaches for routing form submissions from WordPress into Salesforce with attribution data included.

    Option 1: Salesforce Web-to-Lead with Hidden Fields

    Salesforce’s native Web-to-Lead generates an HTML form you embed on your WordPress site. The form posts directly to Salesforce’s submission endpoint. To include attribution data, add hidden input fields to the generated form HTML with the Salesforce API names for your custom fields (e.g., UTM_Source__c, UTM_Campaign__c). A JavaScript snippet reads the cookies at page load and populates the hidden fields before the visitor submits. This approach requires zero third-party integration tools and works as long as the cookie values are present when the form renders.

    Option 2: WordPress Form Plugin with Salesforce Integration

    Plugins like Gravity Forms, WPForms, and Fluent Forms have native or add-on integrations with Salesforce that map form fields to Salesforce fields on submission. Add hidden fields to your WordPress form that read the UTM cookies (populated by JavaScript), then map those hidden fields to your custom Salesforce Lead fields in the plugin’s integration settings. This gives you full control over the form design on your WordPress site while routing to Salesforce natively. The hidden field population script needs to fire after the form renders — move it to after the form HTML or use a DOMContentLoaded event listener if the default timing causes blank values.

    Option 3: Zapier or Make (Integromat)

    If your form plugin does not have a direct Salesforce integration, use Zapier or Make to bridge the submission to Salesforce. The form plugin sends a webhook to Zapier, Zapier maps the fields to a Salesforce “Create Lead” action. Make sure your hidden UTM fields are included in the webhook payload from the form plugin — if they are not mapped as outputs in the plugin’s webhook settings, they will not arrive in Zapier. The downside of this path is added latency (Zapier can introduce a delay of a few minutes) and a dependency on the connection staying active and the Zap not hitting errors.

    Copying Attribution From Lead to Opportunity in Salesforce

    When a Salesforce Lead converts to a Contact and Opportunity, custom field values on the Lead do not automatically transfer. To get attribution onto the Opportunity (which is where deal value lives and where revenue reporting happens), you need an automation to copy the fields at conversion time.

    The cleanest approach is a Salesforce Flow:

    1. Trigger: Record-triggered Flow on Opportunity creation (when IsWon is false and the Opportunity has a converted Lead source)
    2. Get Records: fetch the related converted Lead using the Opportunity’s associated Contact’s ConvertedFromLeadId
    3. Update Records: copy each custom attribution field from the Lead to the Opportunity

    Once this is in place, every new Opportunity has the original Lead’s UTM data on it, and your Opportunity reports can filter and group by attribution fields without manual data entry.

    Reporting: Which Channels Produce Closed Revenue

    With attribution on Opportunities, you can run the most important report in your marketing stack: closed revenue by source channel.

    In Salesforce Reports, create an Opportunity report filtered to Closed Won and group by your UTM Medium field. This shows revenue breakdown by channel: cpc (paid search), organic, email, social, direct. Compare this to your lead volume by source (a separate Leads report grouped by UTM Medium) to identify which channels convert leads to closed deals at the highest rate — which is frequently very different from which channels produce the most leads by volume.

    For campaign-level analysis, add UTM Campaign as a second grouping to see which specific campaigns produce the most closed revenue, not just the most form fills. The UTM Term field gives you keyword-level closed deal data for paid search — which searches are actually worth the click cost versus which generate leads that never close.

    Google Ads Offline Conversion Upload

    If your WordPress forms capture GCLID into a Salesforce custom field, you have what you need to close the loop with Google Ads. When an Opportunity reaches Closed Won, the GCLID, close date, and deal value can be uploaded to Google Ads as an offline conversion event. This tells Google Ads which ad clicks produced actual customers — not just form fills — and its Smart Bidding adjusts to favor the keywords and audiences that generate revenue.

    Two ways to implement this:

    • Salesforce Flow + Google Ads API: A record-triggered Flow fires when an Opportunity reaches Closed Won. The Flow calls the Google Ads offline conversions API via a connected app or an outbound HTTP callout, posting the GCLID and conversion details. This is fully automated once configured — no CSV exports, no manual steps.
    • Manual CSV upload: Export Closed Won Opportunities from a Salesforce report filtered by a date range, include the GCLID column, format the export as the Google Ads offline conversion import template (columns: Google Click ID, Conversion Name, Conversion Time, Conversion Value, Conversion Currency), and upload via Google Ads > Goals > Conversions > Offline conversion imports. This approach works without any API integration and is a solid starting point before investing in the automated path.

    What the Full Stack Looks Like

    When everything is connected:

    • A visitor clicks a Google Ad and arrives on your site with UTM parameters and a GCLID in the URL
    • The UTM capture script stores all parameters and the GCLID in cookies
    • The visitor browses several pages, then submits a contact form
    • Hidden fields read the cookies and submit UTMs and GCLID alongside the form data
    • The form creates a Salesforce Lead with UTM Source = google, UTM Medium = cpc, UTM Campaign = your campaign name, GCLID = the click value
    • A sales rep works the lead, converts it, and an Opportunity is created
    • A Salesforce Flow copies all attribution fields from the Lead to the Opportunity
    • When the Opportunity closes, the GCLID uploads to Google Ads as an offline conversion
    • Google Ads Smart Bidding optimizes toward the keywords that produce closed deals, not just form fills

    The setup takes a few hours across WordPress, Salesforce, and Google Ads. The payoff is that your Salesforce Opportunity reports reflect actual channel performance and your Google Ads campaigns optimize on revenue, not lead volume.

    For a WordPress attribution layer that handles UTM capture, hidden field population, CRM routing, and Google Ads offline conversion upload as a connected system — rather than assembling each piece separately — Sales Provenance integrates everything described here. Related reading: UTM parameter tracking on WordPress, CRM integration for WordPress, HubSpot and WordPress lead tracking, Pipedrive and WordPress lead tracking, and Google Ads conversion tracking for WordPress.

  • Pipedrive and WordPress: How to Track Lead Source Through to Your CRM

    Pipedrive is one of the most widely used CRMs for small and mid-sized businesses, and it pairs naturally with WordPress — Pipedrive handles the pipeline, WordPress handles the website where leads come from. The problem most Pipedrive + WordPress setups run into is the same one that affects every CRM pairing: leads arrive in Pipedrive with no source data. You can see that you have a new contact, but not where they came from, which campaign drove the visit, or which keyword they searched before they filled out the form.

    This guide covers how to wire Pipedrive and WordPress together so that every contact in your pipeline carries the full attribution trail from the session that produced the lead.

    What Pipedrive Does and Does Not Track by Default

    Pipedrive does not have native website tracking the way HubSpot does. When a form submits from your WordPress site into Pipedrive — whether via Pipedrive’s web forms, a WordPress form plugin with a Pipedrive integration, a webhook, or Zapier — the contact record contains whatever fields you sent it. If you did not send source data, the contact has no source data.

    Pipedrive does have a “Source” field on contacts and deals (visible under the contact’s details as a dropdown), and it has a basic marketing source tracking feature for Pipedrive-hosted web forms. Neither of these gives you the granular campaign-level UTM data you need to answer which specific campaign, channel, or keyword produced the lead. That requires custom fields and a UTM capture layer on your WordPress site.

    Setting Up UTM Capture in WordPress

    The foundation of reliable Pipedrive attribution is capturing UTM parameters from the visitor’s landing URL and carrying them through to the form submission. The process is the same regardless of which CRM you use:

    1. When a visitor lands on your site with UTM parameters in the URL, capture them to first-party cookies. A small JavaScript snippet reads utm_source, utm_medium, utm_campaign, utm_term, and utm_content from the URL if they are present, and writes them to cookies with a 30-day expiration. The cookies persist across page navigation — so a visitor who lands on a blog post, browses to your services page, and submits a contact form there still carries the UTMs from their original landing URL.
    2. Add hidden form fields that read the cookie values at submission time. For each UTM parameter, add a hidden input field to your contact form. A JavaScript snippet reads the cookies and populates the hidden fields when the form loads. When the visitor submits, the UTM values travel alongside their name, email, and message.
    3. Also capture the gclid (Google click identifier) and fbclid (Facebook click identifier) using the same cookie approach. These identifiers are required for offline conversion upload to Google Ads and Meta, respectively — they connect the closed deal in Pipedrive back to the specific ad click that started the journey.

    Custom Fields to Create in Pipedrive

    Before connecting your forms, create custom fields in Pipedrive to hold the attribution data. In Pipedrive, go to Settings > Data Fields and add these as custom fields on the Person or Lead object (and mirror them on the Deal object):

    • Lead Source Campaign (text) — maps from utm_campaign
    • Lead Source Medium (text) — maps from utm_medium
    • Lead Source Term (text) — maps from utm_term (keyword for paid search)
    • Lead Source Content (text) — maps from utm_content (ad variation identifier)
    • Landing Page (text) — the first page the visitor landed on, captured from a cookie set on first pageview
    • gclid (text) — Google click identifier, for Google Ads offline conversion upload
    • fbclid (text) — Facebook click identifier, for Meta offline conversion upload

    Use the same field names on both Person and Deal objects so that when a deal is created from a person, you can easily copy the attribution data across. Pipedrive does not auto-copy custom person fields to deals, but a workflow automation (Pipedrive Automations) can handle this.

    Connecting WordPress Forms to Pipedrive

    There are three main approaches for routing WordPress form submissions into Pipedrive with attribution data:

    Option 1: Pipedrive’s Native Web Forms

    Pipedrive offers hosted web forms that submit directly into your pipeline. You can embed these forms on your WordPress site via iframe or JavaScript embed. The advantage is zero integration work — submissions land in Pipedrive natively. The limitation is that Pipedrive’s web forms do not automatically read UTM cookies from your WordPress site, so you need a small script that detects the form’s hidden fields (or uses Pipedrive’s URL parameter feature) and populates them from the cookies before submission.

    Option 2: WordPress Form Plugin + Webhook to Pipedrive API

    Most WordPress form plugins (Gravity Forms, WPForms, Fluent Forms, Contact Form 7 with add-ons) support sending a webhook on form submission. Point the webhook at Pipedrive’s Persons API endpoint (POST https://api.pipedrive.com/v1/persons) and map your form fields — including the hidden UTM fields — to Pipedrive person fields in the webhook payload. This keeps the form on your site (full design control, no iframe) and routes submissions directly into Pipedrive without Zapier.

    The webhook payload maps field names to Pipedrive field keys. For custom fields, use the numeric field key from Pipedrive’s API (visible under Settings > Data Fields > each field’s API key):

    {
      "name": "{{name}}",
      "email": [{"value": "{{email}}", "primary": true}],
      "phone": [{"value": "{{phone}}", "primary": true}],
      "abc1234": "{{utm_source}}",
      "def5678": "{{utm_campaign}}",
      "ghi9012": "{{gclid}}"
    }

    Option 3: Zapier or Make (Integromat)

    If your form plugin does not support direct webhooks, use Zapier or Make to bridge the form submission to Pipedrive. The tradeoff is added latency (Zapier introduces a delay, which matters if your team has a fast follow-up process) and a dependency on a third-party service staying connected. Make sure the hidden UTM fields are included in the data your form plugin sends to Zapier, then map them to the custom Pipedrive fields in the Zap.

    Pipedrive Automations: Copy Attribution to Deals

    Once attribution data is on the Person record, you need it on the Deal record to run deal-level reporting. Create a Pipedrive Automation that triggers when a new Deal is created and copies the person’s custom attribution fields to the deal. The automation uses Pipedrive’s field update action:

    1. Trigger: Deal created
    2. Action: Update deal — set Lead Source Campaign from linked person’s Lead Source Campaign field (and repeat for each attribution field)

    This runs automatically every time a deal is created from a person who has attribution data, and it means your deal pipeline reports can filter and group by source without manual data entry.

    Reporting: Which Channels Produce Deals

    With attribution on deals, you can run the most important report in your marketing stack: which channel produces the most closed deals (not just the most leads).

    In Pipedrive, go to Reports > Deals and group by your Lead Source Medium custom field. Filter to closed/won deals only. This shows you the breakdown of closed revenue by channel — organic search, paid search (cpc), email, direct, social. Compare this to your lead volume by source to see which channels convert leads to deals at the highest rate, which is often very different from which channels produce the most leads.

    For more granular analysis, use the Lead Source Campaign field to see performance by specific campaign, and the Lead Source Term field to see which keywords are actually closing — not just generating clicks.

    Closing the Loop With Google Ads Offline Conversions

    If your WordPress forms capture gclid into a Pipedrive custom field, you have what you need to tell Google Ads which clicks produced real deals — not just form fills. When a deal closes in Pipedrive, export the gclid, the deal close date, and the deal value, and upload this to Google Ads as an offline conversion event.

    Two ways to do this:

    • Pipedrive Automations + Google Ads API: A Pipedrive workflow automation can fire a webhook when a deal reaches Won status. That webhook posts the gclid and conversion data to the Google Ads offline conversions API. This is fully automated once set up — no manual CSV exports.
    • Manual CSV upload: Export won deals from Pipedrive filtered by a date range, include the gclid column, format as the Google Ads offline conversion import template, and upload via Google Ads > Goals > Conversions > Offline conversion imports. This works without any additional integration and is a good starting point before investing in the automated path.

    The result: Google Ads learns which keywords and ad variations produce customers, not just form fills, and its smart bidding optimizes toward the traffic that actually converts to revenue.

    What the Full Stack Looks Like

    When everything is connected:

    • Visitor clicks a Google Ad for “CRM for small business” and arrives on your site with utm_source=google, utm_medium=cpc, utm_campaign=crm-smb, and a gclid
    • The UTM capture script stores all parameters in cookies
    • The visitor browses, then submits a contact form three pages later
    • Hidden fields read the cookies and submit UTMs + gclid alongside the form data
    • The form webhook creates a Pipedrive person with Lead Source Medium=cpc, Lead Source Campaign=crm-smb, gclid=[value]
    • A Pipedrive Automation creates a deal and copies all attribution fields to it
    • When the deal closes 30 days later, the gclid uploads to Google Ads as an offline conversion
    • Google Ads bidding improves toward keywords that produce revenue

    Building this end-to-end takes a few hours of setup. The payoff is that every marketing decision is grounded in deal data rather than form-fill counts.

    For a WordPress attribution layer that handles UTM capture, hidden fields, CRM routing, and Google Ads offline conversion upload as a unified system — rather than assembling each piece separately — Sales Provenance integrates everything described here. Related reading: UTM parameter tracking on WordPress, CRM integration for WordPress, HubSpot and WordPress lead tracking, and Google Ads conversion tracking for WordPress.

  • How to Audit Your WordPress Attribution Setup: A Step-by-Step Checklist

    Most WordPress marketing attribution setups are broken in at least one place, and most businesses do not know it. The tracking code is installed, the forms are submitting, leads are showing up in the CRM — but the lead source fields are blank, or the campaign data is wrong, or Google Ads is optimizing toward the wrong conversions. The setup looks like it is working until you try to use the data and realize you cannot trust it.

    This guide walks through every layer of a WordPress attribution stack, how to test each one, and what to look for when something is wrong. Run through this checklist when you are setting up attribution for the first time, when you inherit a site with existing tracking, or when you suspect your data has drifted from reality.

    Layer 1: UTM Parameter Capture

    UTM capture is the foundation. If it breaks, every layer above it is also broken — forms submit without source data, CRM contacts have no attribution, and Google Ads reports show only blank or direct traffic.

    How to test it:

    1. Build a test URL with UTM parameters: append ?utm_source=test&utm_medium=audit&utm_campaign=attribution-check to any page on your site.
    2. Open the URL in an incognito window. Navigate to a second page on the site (like the contact page) without the UTM parameters in the URL.
    3. Open browser developer tools, go to Application, and look for cookies. You should see cookies named something like utm_source, utm_medium, utm_campaign (the exact names depend on how your capture script is written) with the values from step 1.
    4. If the cookies are present after navigating away from the original UTM URL, capture is working. If the cookies disappear when you navigate away, the script is running on page load rather than storing to persistent cookies — this means cross-page attribution is broken.

    Common failure modes:

    • Script only reads UTMs on the landing page and passes them directly to a form hidden field without storing to cookies — breaks when the visitor browses to a different page before submitting
    • Cookie expiration set to session only — the UTM data disappears when the browser closes, losing attribution for visitors who return days later
    • Script fires after the page load event fires, missing UTMs if the visitor navigates away very quickly
    • UTM parameters getting stripped by a redirect on the landing page — check whether any redirect (www to non-www, HTTP to HTTPS, trailing slash canonicalization) removes query parameters

    Layer 2: Hidden Form Fields

    Hidden fields read the UTM cookies at form submission and pass them to your CRM or email system. If the fields are configured but empty on submission, the UTM capture is failing. If the fields do not exist, attribution data never reaches the CRM.

    How to test it:

    1. Build a test URL with UTM parameters as in Layer 1.
    2. Open the URL in an incognito window and navigate to a page with a form.
    3. Open developer tools and look at the form in the Elements tab. Find the hidden input fields — they should have names matching your UTM parameters (utm_source, utm_campaign, etc.) and values populated from the cookies.
    4. If the hidden fields are present but empty, the script reading cookies into fields is not running. If the hidden fields are not present at all, the form setup is incomplete.
    5. Submit a test form and check the submission in your CRM or form submission log. The UTM fields should appear with the test values you set in step 1.

    Common failure modes:

    • Hidden fields added to the form but the script reading cookies into them is missing or not loading
    • Script runs before the form renders, so the hidden fields do not exist when the script tries to populate them — usually fixed by deferring the script or moving it to after the form HTML
    • Form uses AJAX submission that bypasses the hidden field population script
    • Multiple forms on the same site with the hidden fields added to only some of them

    Layer 3: Form-to-CRM Connection

    This layer routes the form submission into your CRM with all fields intact, including the attribution fields. A broken connection here means leads still get captured somewhere (email inbox, form plugin database) but never reach the CRM with their source data.

    How to test it:

    1. Submit a test form using the UTM test URL from Layer 1. Use a name and email address you control so you can find the submission.
    2. Check your CRM immediately after submission. Look for the test contact and inspect their properties. You should see Lead Source, Lead Campaign, Lead Medium (or whatever custom properties you created) populated with the values from your UTM test.
    3. If the contact appears but the attribution fields are blank, the form-to-CRM mapping is missing the custom field connections. If the contact does not appear at all, the connection itself is broken.

    Common failure modes:

    • Form plugin updated and the native CRM integration add-on stopped working — check the plugin’s integration settings page for errors
    • CRM API key expired or revoked
    • Custom attribution properties exist in the CRM but the field mapping in the form plugin was not updated to include them
    • Webhook URL changed (CRM rotated an endpoint) and the form plugin is still sending to the old URL
    • Form submissions going to a Zapier trigger that stopped working — check Zapier task history for failures

    Layer 4: Google Analytics 4 Conversion Tracking

    GA4 should record a conversion event when a form is submitted or when a visitor reaches a thank-you page. If this is broken, GA4 reports show zero conversions, and you cannot use GA4 for channel-level attribution.

    How to test it:

    1. Install the Google Analytics Debugger Chrome extension, or use GA4’s DebugView (in GA4 Admin > DebugView).
    2. Submit a test form on your site while DebugView is active. You should see an event fire with the name you configured (form_submit, generate_lead, or a custom event name).
    3. In GA4 under Reports > Conversions, check that the conversion action has recorded at least one conversion. Allow up to 24 hours for conversions to appear in standard reports, but DebugView shows events in real time.

    Common failure modes:

    • GA4 tracking code installed but the conversion event trigger in Google Tag Manager was not set up or is misconfigured
    • Thank-you page redirect is not actually loading the thank-you page URL — if a form submits via AJAX and shows a success message without a page redirect, a thank-you page trigger never fires
    • Form plugin’s built-in conversion event fires but Google Tag Manager is configured to fire a duplicate event, creating double-counted conversions
    • GA4 property was switched but Google Tag Manager still has the old Measurement ID

    Layer 5: Google Ads Conversion Import

    Google Ads needs to receive conversion signals to optimize campaign bidding. If GA4 conversions are not imported into Google Ads, or if the import is set up but not matching, the Google Ads account is flying blind on which clicks produce leads.

    How to test it:

    1. In Google Ads, go to Goals > Conversions. Find your imported conversions and check the “Status” column. It should show “Recording conversions” and have recent conversion data. “No recent conversions” with a recent campaign spend is a red flag.
    2. Check the conversion window setting. If it is set to 30 days and your sales cycle is longer, conversions are being cut off before the deal closes.
    3. In Google Ads under Diagnostics > Conversion tracking diagnostics, check for warnings about unverified conversions or tags not firing.

    Common failure modes:

    • GA4 conversion is configured but the import link between GA4 and Google Ads is not set up under Tools > Linked accounts
    • Multiple conversion actions counting the same event — inflates conversion numbers and confuses bidding
    • Auto-tagging is disabled in Google Ads settings — gclid values do not get appended to ad click URLs, so GA4 cannot attribute sessions to specific ads
    • Conversion action marked as “Don’t use for bidding” when it should be the primary bidding signal

    Layer 6: CRM Deal Attribution

    This is the final layer that most setups never reach. It connects closed revenue in the CRM back to the channels and campaigns that produced it. If this is missing, you can count leads by source but cannot answer which sources produce paying customers.

    How to test it:

    1. Find five to ten recently closed deals in your CRM. Open each contact record and look for the attribution custom properties (Lead Source, Lead Campaign, etc.).
    2. If the properties are blank on most records, the hidden field population is failing at submission — go back to Layer 2.
    3. If the contact record has attribution but the deal record does not, the attribution properties are not being copied to the deal object at deal creation — this requires a workflow or field duplication setup in your CRM.
    4. Run a simple report: closed deals grouped by Lead Source Medium (cpc, organic, email, direct). If everything shows as blank or direct, attribution is broken at the contact level.

    Common failure modes:

    • Attribution properties exist on the Contact object but not on the Deal object — deal-level reporting cannot filter by source
    • CRM workflow that was supposed to copy source properties from contact to deal was disabled or never created
    • Lead source field getting overwritten on repeat form submissions — if a contact submits twice and the second submission has different UTMs, the original source is lost

    Running the Full Audit

    Work through these layers in order. Each layer depends on the one below it — if UTM capture is broken, everything above it is also broken, so fix from the bottom up. The most common pattern in broken setups is that the visible parts look fine (forms submit, leads appear in the CRM) but the invisible parts (UTM cookie storage, hidden field population, CRM field mapping) have a gap that silently drops attribution data.

    Run a fresh test submission after fixing each layer before moving to the next one. A single test that passes through the whole stack end-to-end — UTM in the URL, form submission, contact in CRM with attribution fields, conversion recorded in GA4 and Google Ads — is the only confirmation that the full stack is working.

    For a WordPress attribution setup where each of these layers is integrated and tested as part of the installation — so you do not inherit a partially working stack and discover the gaps six months later when you try to run a channel report — Sales Provenance handles UTM capture, hidden field population, CRM routing, and Google Ads conversion tracking as a connected system. Related reading: UTM parameter tracking on WordPress, Google Tag Manager for WordPress, CRM integration for WordPress, and Google Ads conversion tracking for WordPress.

  • HubSpot and WordPress: How to Track Lead Source Through to Your CRM

    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:

    1. 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.
    2. 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.
    3. 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:

    1. 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).
    2. 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.
    3. 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.

  • GA4 Attribution Models for Lead Generation: Which One to Use

    GA4 changed how attribution works, and most lead generation businesses never updated how they think about it. Universal Analytics defaulted to last-click. GA4 defaults to data-driven attribution — a model that distributes conversion credit across multiple touchpoints using machine learning. For businesses that run Google Ads and care about which channels actually drive leads, this shift has real implications for what the reports say and which channels look productive.

    This guide covers the GA4 attribution models, which one fits different types of lead generation businesses, and how to configure your setup so the data you act on is actually telling you something useful.

    The GA4 Attribution Models

    GA4 offers several attribution models. Here is what each one does and when it makes sense:

    Data-Driven Attribution (GA4 Default)

    Data-driven attribution (DDA) uses machine learning to assign credit to touchpoints based on their actual contribution to conversions, not a fixed rule. If organic search tends to introduce visitors who later convert after seeing a paid ad, DDA gives organic some credit for those conversions rather than awarding everything to the paid click.

    In theory, DDA is the most accurate model. In practice, it requires volume — Google recommends at least 400 conversions over 30 days per conversion action for DDA to work well. For low-volume lead generation businesses (fewer than 400 form submissions or calls per month), DDA falls back to last-click anyway. If your lead volume is below this threshold, DDA looks sophisticated but behaves like last-click.

    Last Click

    All conversion credit goes to the final touchpoint before the conversion. Simple, auditable, predictable. The problem with last-click is that it systematically undercredits awareness channels. A prospect who found you through organic search, visited twice through direct, then converted after clicking a branded paid ad shows the branded paid ad driving 100% of conversions — even if they never would have heard of you without the organic post that introduced them.

    For businesses that run single-channel campaigns or that just want a clear, consistent number for Google Ads performance, last-click works. For businesses evaluating multi-channel mix, it distorts the picture.

    First Click

    All credit goes to the first touchpoint. The mirror image of last-click, first-click is useful for understanding which channels introduce new prospects. It overcredits awareness channels and undercredits conversion-driving channels. Rarely used as a primary model; sometimes useful as a second lens when evaluating which channels are generating top-of-funnel reach.

    Linear

    Credit is distributed equally across every touchpoint in the conversion path. A prospect with four touchpoints gives each one 25% of the conversion. Linear is easy to explain and avoids extreme crediting at either end of the funnel. It also treats all touchpoints as equally valuable, which is rarely true — a brand awareness display impression at day one is not the same contribution as a branded search click on the day of conversion.

    Position-Based (40-20-40)

    40% of credit goes to the first touchpoint, 40% to the last, and the remaining 20% is divided evenly across any middle touchpoints. This model reflects the belief that both introduction (first touch) and conversion (last touch) are the most important moments, with middle touchpoints playing a supporting role. A reasonable compromise for businesses that want to value both acquisition channels and conversion channels.

    Time Decay

    Touchpoints closer in time to the conversion receive more credit. A touchpoint that happened yesterday gets more credit than one that happened two weeks ago. Time decay makes intuitive sense for short sales cycles — if a prospect researched your service and converted within 48 hours, the recent touchpoints genuinely drove the decision. For long B2B sales cycles where an initial blog post read six months ago actually started the relationship, time decay dramatically undercredits early-stage content.

    Which Model Fits Your Business

    High-volume lead gen with Google Ads as primary channel

    If you run Google Ads and generate more than 400 conversions per month, data-driven attribution is worth using for campaign optimization. The model’s ability to learn from actual conversion paths and adjust bid optimization signals accordingly produces better bidding than last-click over time. Use DDA in GA4 and configure Google Ads to import GA4 conversions or use Google Ads’ own DDA model (which has access to more signal from the Google ecosystem).

    Low-volume lead gen with Google Ads

    If you generate fewer than 400 conversions per month, data-driven falls back to last-click. Use last-click explicitly so you know what you are reporting against. The honest answer for many local service businesses is that last-click is the practical model — volume is too low for machine learning to improve on a simple rule.

    Multi-channel mix with SEO + paid

    If organic search and paid search both run, and you want to understand how they interact, position-based (40-20-40) or linear give you a better picture than last-click. SEO regularly introduces prospects who convert through paid; last-click attribution makes paid look like the hero and SEO look unproductive. This is why SEO budgets get cut — the model does not credit introduction. A position-based model shows both channels contributing to the same conversion path.

    Long sales cycle B2B

    First-click or linear models work better than last-click or time decay for long B2B sales cycles. If a prospect reads your content in month one and converts in month six, last-click gives all credit to the bottom-of-funnel action that closed them. First-click or linear preserves credit for the content that started the relationship. For B2B lead generation where the buying journey spans multiple months, first-click is often the most honest lens for evaluating which channels generate new pipeline.

    Configuring Attribution in GA4

    GA4 lets you set attribution at the property level. Here is where to find and adjust it:

    1. Go to GA4 Admin > Property Settings > Attribution Settings
    2. Under “Reporting attribution model,” choose the model you want applied to GA4 conversion reports
    3. Under “Lookback window,” set how far back in the conversion path GA4 should credit touchpoints (default is 30 days for acquisition channels, 3 days for engagement; for longer sales cycles, extend the acquisition window to 60 or 90 days)

    One important nuance: the attribution model you set in GA4 affects GA4 reports only. Google Ads uses its own attribution model for bidding optimization, set separately within the Google Ads account under Measurement > Attribution. If you import GA4 conversions into Google Ads, the Google Ads model applies for bidding purposes regardless of your GA4 setting. Keep both aligned if you want reporting and bidding to reflect the same logic.

    The Lookback Window Problem

    Attribution settings that get changed without changing the lookback window produce misleading data. The lookback window controls how far back from a conversion GA4 will look for touchpoints to credit. The default 30-day window is too short for service businesses with longer consideration periods.

    A homeowner searching for a roofing contractor might research for 45 to 60 days before contacting anyone. A business owner evaluating a marketing agency might consume content for 90 days before submitting a contact form. If the lookback window is 30 days, any touchpoint from day 31 onward gets no credit — and the channels that generate initial awareness (organic blog posts, display campaigns, referral traffic) systematically disappear from the attribution picture.

    For most lead generation businesses, a 60-day lookback window is more accurate than the default. For B2B businesses with long sales cycles, 90 days is appropriate. Set this in the same Attribution Settings panel in GA4 Admin.

    Google Ads Attribution vs GA4 Attribution

    One source of confusion in lead generation attribution is the difference between what Google Ads reports and what GA4 reports. They count conversions differently and can show very different numbers for the same campaigns:

    • Google Ads counts a conversion when a conversion action fires, attributed to the ad click that preceded it. A conversion action fires once, but can be counted multiple times if a user converts multiple times within the lookback window.
    • GA4 counts sessions and users, and reports conversions based on your configured attribution model applied to GA4-tracked events.

    The result: Google Ads reports and GA4 reports almost never match on conversion count, even for the same time period. This is not a tracking error. It is the natural result of two systems counting different things with different methodologies. Using both as directional signals rather than precise counts, and not trying to reconcile them to the same number, is the right frame.

    What Good Attribution Actually Looks Like

    No single attribution model tells the complete story. The businesses that make good channel decisions do not pick one model and treat it as truth — they use multiple views:

    • Last-click for Google Ads optimization (it is what bidding algorithms most reliably use)
    • First-click or linear for understanding which channels generate new pipeline
    • Offline conversion data (deal-level revenue from the CRM) uploaded back into Google and Meta to close the loop between lead attribution and actual closed revenue

    The attribution model question matters most at the top — what do you tell Google Ads to optimize toward? For most lead generation businesses running Google Ads, the honest answer is: use last-click if you are below 400 conversions per month, and use data-driven if you are above it. Set the lookback window to 60 days. Import CRM-verified conversions as offline conversions when you can. Everything else is secondary to having clean, complete conversion data flowing into the system in the first place.

    For a complete guide to getting attribution data from your website into Google Ads and your CRM without custom development: Sales Provenance handles UTM capture, form-to-CRM routing, and offline conversion upload as an integrated layer. Related reading: Google Ads conversion tracking for WordPress, UTM parameter tracking on WordPress, and closed-loop reporting for WordPress.

  • CRM Integration for WordPress: How to Get Lead Source Data Into Your Sales Pipeline

    Most WordPress marketing stacks stop at the lead. You install a contact form, connect GA4, maybe add call tracking, and calls or form submissions start flowing in. But the moment a lead leaves your website and enters your sales process, the marketing data disappears. You know which channel drove the visit. You have no idea which channel drove the client.

    CRM integration is what closes that gap. When the lead source data captured on your WordPress site flows into your CRM alongside the contact record, every deal in your pipeline carries its origin story: which campaign, which keyword, which ad, which referral source. Your sales team works with context. Your marketing reports reflect what actually happened.

    This guide covers how to wire WordPress lead capture to a CRM so that lead source data survives the handoff from marketing to sales.

    What Gets Lost Without CRM Integration

    Without a direct connection between your WordPress forms and your CRM, marketing-to-sales handoffs look like this: a form submission fires, the data lands in your email inbox or a spreadsheet, someone manually creates a CRM deal, and the attribution data is either forgotten or typed in wrong. By the time you want to know which channel drove closed revenue, the information is gone.

    The specific losses:

    • Lead source: which channel (Google Ads, organic, Facebook, email referral) drove the contact
    • Campaign and keyword: which campaign, ad group, or keyword produced the lead
    • Landing page: which page the contact first landed on
    • UTM parameters: the full campaign tracking data present in the URL when the contact arrived
    • gclid: Google Ads click identifier that enables offline conversion upload

    When these fields are missing from the CRM record, you cannot answer the question that matters most in marketing: which channels and campaigns produce clients, not just leads?

    The Integration Architecture: What Needs to Connect

    A complete WordPress-to-CRM integration has four layers:

    1. Attribution capture on landing: when a visitor arrives, capture UTM parameters and gclid from the URL and store them in first-party cookies that persist across pages. This is the foundation everything else depends on.
    2. Hidden fields in forms: your contact forms include hidden fields that read the stored cookie values and submit them alongside the contact’s name, email, and message.
    3. Form-to-CRM connection: when the form submits, the data routes to your CRM automatically — no manual entry, no email-to-spreadsheet-to-CRM chain.
    4. Deal-level attribution: the CRM record for each contact and deal includes the lead source fields, so sales can see them and marketing can report on them.

    The UTM capture and hidden field setup is covered in detail in the UTM parameter tracking guide. This post focuses on the form-to-CRM layer and how to structure the deal data for reporting.

    Common WordPress Form Plugins and CRM Connections

    Gravity Forms

    Gravity Forms has native add-ons for HubSpot, Salesforce, Zoho, Pipedrive, and ActiveCampaign. The add-ons map form fields to CRM properties directly in the Gravity Forms editor. For attribution fields: map your hidden UTM fields to custom CRM contact properties you create in advance. No code required for the basic connection; custom field mapping takes about 20 minutes of setup per CRM.

    WPForms

    WPForms Pro includes a Zapier integration and native connections to Salesforce, HubSpot, and Drip. The Zapier path works for most other CRMs — a WPForms submission triggers a Zap that creates or updates a contact, with field mapping in the Zapier editor. Attribution fields flow through the same mapping as any other form field.

    Contact Form 7

    Contact Form 7 does not have native CRM integrations. The common path is Flamingo (the CF7 companion plugin that stores submissions in WordPress) plus a Zapier connection, or a dedicated plugin like CF7 to Webhook that fires the form data to a CRM’s API endpoint. Both work; the Zapier path is easier to maintain; the webhook path is faster and avoids a third-party dependency.

    Fluent Forms

    Fluent Forms Pro has built-in integrations with HubSpot, Zoho, Pipedrive, ActiveCampaign, Salesforce, and others. Field mapping works the same way as Gravity Forms: map hidden attribution fields to custom CRM properties. Fluent Forms also supports webhooks natively for direct API connections to CRMs not on the native list.

    Setting Up Custom Lead Source Fields in Your CRM

    Before you can map attribution data from your forms, you need somewhere to put it in your CRM. Most platforms let you create custom contact and deal properties. The standard set to create:

    • Lead Source: text field, maps from UTM source (google, facebook, email, etc.)
    • Lead Medium: text field, maps from UTM medium (cpc, organic, referral, etc.)
    • Lead Campaign: text field, maps from UTM campaign
    • Lead Term / Keyword: text field, maps from UTM term (for paid search)
    • Landing Page: URL field, maps from the first page the contact visited
    • gclid: text field, maps from the Google click identifier (for offline conversion upload)

    In HubSpot and Zoho, these are created under Properties settings. In Pipedrive, they are custom fields on the Person or Deal object. In Salesforce, they are custom fields on the Lead or Contact object. Set them all to text type, mark them as visible to sales, and add them to the deal/contact view so they surface without hunting.

    The Webhook Path: Direct Form-to-CRM Without Zapier

    Zapier is convenient but adds latency and cost, and the free tier limits trigger volume. Most CRMs offer a native API that accepts a POST request with contact data. If your form plugin supports webhooks — Gravity Forms, WPForms Pro, Fluent Forms all do — you can fire form submissions directly to the CRM API endpoint and skip the middleware entirely.

    The general pattern:

    1. Get your CRM API key and find the contact creation endpoint in the CRM’s API documentation
    2. In your form plugin, add a webhook action that fires on submission
    3. Map your form fields (including attribution hidden fields) to the CRM’s expected field names
    4. Set the Content-Type header to application/json and the Authorization header to your API key
    5. Test with a form submission and verify the contact appears in the CRM with all attribution fields populated

    HubSpot’s Contacts API, Pipedrive’s Persons API, and Zoho CRM’s Leads API all support this pattern. For most WordPress + CRM combinations, a working webhook setup takes under an hour. Once it is running, every form submission lands in the CRM within seconds, with attribution data intact.

    Structuring the CRM Deal for Marketing Reporting

    Getting the data into the CRM is half the problem. The other half is making sure the data is structured so you can report on it. Two practices that matter:

    Attach attribution to the deal, not just the contact

    In many CRMs, lead source fields live on the contact record. If a contact submits a form and becomes a deal, the deal needs the attribution fields too — not just the contact. When you are running a close-rate report (which channel drives clients, not just leads), the query runs against deals, not contacts. Either duplicate the fields on the deal object or make sure your CRM copies them from the contact at deal creation.

    Preserve first-touch attribution

    If a contact submits a form twice — first from organic search, then six months later from a remarketing ad — your UTM cookies will capture the most recent values. Your CRM should store the first submission’s attribution separately and not overwrite it on subsequent contacts. In HubSpot, this is the “Original source” property set. In Pipedrive and Zoho, you need to set the custom lead source fields as write-once: populate at creation, do not update on subsequent activity. First-touch attribution tells you which channel introduced the relationship; last-touch tells you which channel prompted the conversion. Both are useful for different decisions.

    Offline Conversion Upload: Closing the Loop With Google and Meta

    CRM integration is also what makes offline conversion upload possible. When a deal in your CRM closes, you know the revenue. If that deal’s CRM record includes a gclid (Google click ID), you can upload the closed deal as an offline conversion to Google Ads. Google uses the gclid to match the conversion back to the exact keyword and ad that drove the original click.

    The result: your Google Ads bidding algorithms optimize toward the keywords that produce clients at your target cost, not just the keywords that produce form submissions. Over time, this is the difference between bidding toward leads (many of which may not convert to revenue) and bidding toward closed revenue (which is what the business actually sells).

    The same principle applies to Meta Ads. The Meta Conversions API accepts offline events — closed deals from your CRM — tied back to the fbclid (Facebook click ID) captured when the lead clicked your ad. Meta uses these events to optimize ad delivery toward the audiences most likely to produce actual clients.

    The offline conversion process is covered in more depth in the Google Ads conversion tracking guide and the Meta Ads conversion tracking guide.

    What a Fully Integrated Stack Looks Like

    When WordPress, your form plugin, and your CRM are connected with attribution data flowing end to end, a single closed deal tells you:

    • Which channel drove the visit (Google Ads, Facebook, organic, email)
    • Which campaign and keyword drove the click
    • Which landing page the contact first saw
    • When the lead came in, how long the sales cycle was, and what the deal was worth

    Aggregate across a year of closed deals and you have a channel close-rate report: which sources produce clients at what revenue, not just which sources produce the most lead volume. That is the report that drives smart marketing budget decisions.

    For a WordPress plugin that handles the attribution capture, hidden field population, CRM routing, and offline conversion upload as a single integrated layer — without custom development for each component — Sales Provenance is built to connect every piece described here. Related reading: UTM parameter tracking on WordPress, Google Ads conversion tracking for WordPress, call tracking for WordPress, and Google Tag Manager for WordPress.

  • Google Tag Manager for WordPress: How to Install, Configure, and Track Everything

    Google Tag Manager is the most useful tool most WordPress marketers have installed and barely use. It ships on millions of sites, handles dozens of tags, and sits between your WordPress site and every analytics and advertising platform you run. Most people use it to paste a GA4 snippet and stop there.

    This guide covers what GTM actually does, how to set it up correctly on WordPress, and how to use it to build the tracking infrastructure your marketing reporting depends on — without touching your theme or writing custom code for every new tag.

    What Google Tag Manager Does (and Why It Matters)

    Tag Manager is a container: a single snippet of JavaScript that loads on every page of your site and then decides what other scripts to fire, when, and under what conditions. Instead of embedding GA4, Meta Pixel, Google Ads conversion tracking, call tracking, and a dozen other scripts directly in your site’s code, you embed GTM once and manage everything else from inside the GTM interface.

    That separation matters for three reasons:

    • Speed of change. Adding a new conversion event or updating a pixel ID takes two minutes in GTM and publishes instantly, without a developer or a WordPress update. Without GTM, every tracking change requires code access or a plugin update.
    • Reliability. Scripts hard-coded into a theme can break on theme updates, plugin conflicts, or PHP version changes. GTM loads independently — your tracking survives site changes that would otherwise break it.
    • Visibility. GTM Preview mode shows you exactly which tags fired, when they fired, and what data they sent. Debugging tracking issues without GTM means guessing. With it, you can see every tag fire in real time.

    Installing GTM on WordPress

    GTM requires two code snippets: one in the <head> of every page, and one immediately after the opening <body> tag. WordPress makes both straightforward without editing theme files.

    Option 1: WPCode (recommended)

    WPCode (formerly Insert Headers and Footers) is a free plugin that lets you inject code into the head and body of your site without touching your theme. Install WPCode, then:

    1. Go to Code Snippets in WPCode and create a new snippet.
    2. Paste the GTM head snippet, set location to “Header,” and activate.
    3. Create a second snippet for the GTM body snippet, set location to “Body (Start),” and activate.

    This method survives theme updates because the code lives in the database, not your theme files. It is the cleanest approach for most WordPress sites.

    Option 2: Theme functions.php

    If you prefer to keep everything in your theme, you can use wp_head and wp_body_open hooks in functions.php to inject the snippets. This works but breaks when you switch themes or update a theme without a child theme in place. Use WPCode unless you have a specific reason to go the functions.php route.

    Verifying installation

    After installing, open GTM Preview mode (click Preview in the GTM dashboard), enter your site URL, and confirm that the GTM container fires on every page. You will see a panel at the bottom of your browser showing all tags in the container. If the container loads, you are set. If it does not, check that both snippets are publishing correctly in WPCode and that a caching plugin is not serving a pre-GTM version of your pages.

    The Three Core Tags Every WordPress Site Needs

    Once GTM is installed, the first tags to add are the ones that feed your analytics and advertising platforms.

    GA4 Configuration Tag

    The GA4 Configuration tag loads the GA4 library on every page and sends a pageview. In GTM, create a new tag, select Google Analytics: GA4 Configuration, enter your Measurement ID (format: G-XXXXXXXXXX), and set the trigger to All Pages. This replaces any GA4 snippet you may have installed directly in your theme — remove the direct snippet if you add it through GTM to avoid duplicate tracking.

    Google Ads Conversion Linker

    If you are running Google Ads, add a Conversion Linker tag alongside your GA4 tag. It runs on All Pages and ensures that click IDs (gclid values from Ads clicks) are properly written to first-party cookies on your domain. Without this tag, conversion attribution can break when a visitor clicks an ad and then navigates across pages before converting. It is a one-setup, no-configuration-needed tag that prevents a common attribution failure.

    Meta Pixel Base Code

    The Meta Pixel base tag loads the Facebook pixel library on every page and fires a PageView event. In GTM, add a Custom HTML tag, paste the pixel code from Meta Events Manager, and set the trigger to All Pages. From there, you add individual event tags (Lead, Purchase, etc.) as separate tags triggered by specific actions.

    Tracking Form Submissions as Conversions

    Most WordPress contact forms do not fire a conversion event by default. GA4 records the session but has no way to know that the session produced a lead. GTM closes that gap.

    Thank-you page trigger

    The most reliable method: redirect form submitters to a dedicated thank-you page (e.g., /thank-you/) after submission. In GTM, create a Page View trigger that fires only on URLs matching /thank-you/. Attach a GA4 event tag (generate_lead or form_submission) to that trigger. When a visitor hits the thank-you page, the conversion fires. This works with any WordPress form plugin — Gravity Forms, WPForms, Contact Form 7, Fluent Forms — because it depends on a URL change rather than form-specific hooks.

    Form submission trigger (no redirect)

    If you use inline success messages instead of a redirect, GTM’s built-in Form Submission trigger fires when any form on the page submits. Add the Form Submission trigger, check “Wait for Tags” and “Check Validation” to avoid firing on invalid submissions, and attach your conversion tag. This requires testing in GTM Preview to confirm it is firing on the right forms and not on search boxes or newsletter signups that share the page.

    UTM Parameter Capture via GTM

    UTM parameters in the URL tell you where traffic came from. Capturing them in first-party cookies and then passing them through form submissions is the foundation of lead source attribution. GTM is the cleanest place to run this script.

    The setup: create a Custom HTML tag that reads UTM values from the URL on page load and writes them to first-party cookies. Set the trigger to All Pages and fire it as one of the first tags in your container. From that point on, any hidden fields in your forms can read those cookie values and include them in each submission.

    The full UTM capture script and cookie-to-hidden-field connection is covered in detail in the UTM parameter tracking guide. GTM is the recommended installation path for that script over WPCode or functions.php because GTM fires reliably across page types, including cached pages where PHP-based hooks can sometimes be skipped.

    Call Tracking Installation via GTM

    Call tracking platforms like CallRail use a JavaScript snippet that swaps phone numbers on the page based on the visitor’s traffic source. GTM is the recommended installation path for this snippet as well: create a Custom HTML tag, paste the call tracking snippet, and fire on All Pages. GTM Preview lets you verify the snippet is loading and that number swaps are firing correctly by simulating different traffic sources.

    The detailed call tracking setup — dynamic number insertion, GA4 integration, and CRM connection — is in the call tracking for WordPress guide.

    GTM Preview Mode: How to Debug Tracking Before It Goes Live

    GTM Preview is the most underused feature in most marketers’ toolkit. Before publishing any new tag, open Preview mode, load your site, and verify:

    • Which tags fired on pageview
    • Which tags fired on form submission (submit a test form)
    • What data was sent with each tag (click the tag name to see the full data layer output)
    • Whether any tags fired unexpectedly or failed to fire

    Common errors you will catch in Preview that are invisible otherwise: tags firing twice (duplicate triggers), tags not firing on form submission (form validation blocking the trigger), and tags firing on the wrong pages (overly broad triggers). Preview shows you the exact sequence of events that occurred during a user session, which makes debugging specific to what actually happened rather than what you expected.

    Versioning and Workspace Management

    GTM versions every published container state automatically. If a tag change breaks something, you can roll back to any prior version in seconds. Before publishing a significant change, add a version note describing what changed and why — this creates an audit trail that matters when multiple people have GTM access or when you are debugging a conversion drop six months later.

    GTM workspaces let you build and test changes in parallel without touching the live container. Use a workspace for every new tag deployment, test in Preview, then merge and publish. This keeps the live container clean and prevents in-progress work from accidentally going live.

    What to Build With GTM After the Basics

    Once GA4, Google Ads conversion linker, Meta Pixel, form conversion tracking, and UTM capture are running, GTM becomes the control layer for everything else:

    • Scroll depth tracking: fire a GA4 event when a visitor scrolls 50 or 75 percent of a page, to understand content engagement without relying on time-on-page metrics.
    • Outbound link clicks: track when visitors click links to external sites (scheduling tools, PDF downloads, phone number links on desktop).
    • Video engagement: if you embed YouTube videos, GTM’s built-in YouTube trigger fires events on play, pause, and completion without custom code.
    • Enhanced conversions for Google Ads: pass hashed first-party data (email address from form submissions) to Google Ads to improve conversion matching rates. GTM handles the hashing and data layer connection.

    For a complete attribution stack that layers UTM capture, form field enrichment, call tracking, and closed-loop revenue reporting on top of a GTM foundation — without requiring custom development — Sales Provenance is built to handle every layer described here as a single WordPress plugin. Related reading: UTM parameter tracking on WordPress, Google Ads conversion tracking for WordPress, and call tracking for WordPress.

  • Call Tracking for WordPress: How to Know Which Marketing Channels Are Driving Phone Calls

    Most WordPress service businesses track form submissions. Fewer track phone calls. That gap creates a systematic blind spot in attribution: if 40 to 60 percent of your leads come through the phone — as they do for most contractors, healthcare practices, law firms, and home service companies — then half your lead data is invisible to your analytics. You cannot accurately attribute revenue to channels you cannot track.

    Call tracking closes that gap. This guide covers how it works, what to set up, and how to connect call data to the same attribution systems your form submissions already feed.

    Why Phone Calls Break Standard Attribution

    When a visitor submits a form on your WordPress site, the thank-you page or confirmation event fires in GA4 and your CRM records the source. The entire chain from click to conversion is digital and trackable.

    When a visitor calls your phone number, none of that happens. The call goes directly to your phone. GA4 records the session that preceded the call but has no way to connect that session to the call itself. Your CRM records the caller’s name and number but not which campaign, keyword, or page drove them to pick up the phone. The attribution chain breaks.

    For a business running Google Ads, this means Google’s smart bidding system is optimizing on form submissions alone — often 40 to 60 percent of your actual conversions. The campaigns that drive calls but not forms look like poor performers in the data. They get reduced budget. You end up defunding channels that were actually working.

    How Dynamic Number Insertion Works

    Dynamic number insertion (DNI) is the technology that connects a phone call back to the traffic source that drove it.

    The mechanism: a JavaScript snippet runs on every page of your WordPress site. When a visitor arrives, the script detects their traffic source — which campaign they came from, which keyword, which channel — and replaces the phone number displayed on the page with a unique tracking number assigned to that source. Someone who arrived from a Google Ads click sees a different number than someone who came from organic search, which sees a different number than someone from Facebook.

    When they call the tracking number, the call is routed to your real phone. The call tracking platform records which number was dialed — and therefore which source, campaign, and keyword drove the call. That data is then passed to GA4 as a conversion event, to Google Ads as an offline conversion, and to your CRM as a lead record with source attribution attached.

    The visitor experience is identical. Only the tracking infrastructure changes.

    Static Numbers vs. Dynamic Numbers: When to Use Each

    Not every number on your site needs to be dynamic. Understanding the distinction saves budget and simplifies setup.

    • Dynamic numbers are for pages that receive paid traffic or organic traffic you want to attribute. Your home page, service pages, and landing pages should use dynamic numbers. Any page a visitor might arrive on from a campaign needs a number that swaps by source.
    • Static tracking numbers are for specific offline channels: a dedicated number in a print ad, a billboard, a direct mail piece, a specific email campaign. These are always the same number for that channel — they do not swap. You are tracking the channel, not the session.
    • Your real business number should only appear in places where source attribution is not a goal: your Google Business Profile (if you are not tracking GBP calls separately), your email signature, directory listings. Calls to this number will not be attributed.

    Choosing a Call Tracking Platform for WordPress

    Three platforms dominate this space for WordPress service businesses:

    • CallRail is the most widely used for small-to-mid service businesses. Strong GA4 integration, Google Ads offline conversion sync, call recording and transcription, and a relatively simple setup. Plans start around $45/month for basic dynamic tracking. The WordPress plugin exists but is optional — the JavaScript snippet installs easily via Google Tag Manager.
    • WhatConverts is a strong alternative with tighter multi-channel attribution, built-in quote request tracking, and more detailed lead management. Better fit for agencies managing multiple clients or businesses that want call, form, and chat attribution in a single platform. Slightly more expensive than CallRail at comparable feature levels.
    • Invoca targets enterprise and agency use cases with signal-level integration directly into Google Ads and Meta. Substantially more expensive. Worth evaluating if you are spending more than $20,000 per month on paid search and need call-level bidding signals at scale.

    For most WordPress service businesses, CallRail is the right starting point. You can migrate to WhatConverts if you need more sophisticated lead management, or graduate to Invoca as ad spend scales.

    Connecting Call Tracking to GA4

    CallRail and WhatConverts both fire GA4 events when a call occurs. Setup:

    1. In your call tracking platform, enable the GA4 integration and provide your Measurement ID.
    2. The platform fires a custom event (typically call_start or phone_call) when someone dials a tracked number. The event includes the call source, campaign, keyword, and duration.
    3. In GA4, mark the call_start event as a conversion. Now phone calls appear alongside form submissions in your conversion reporting, broken down by source and campaign.
    4. In Google Ads, import the GA4 call conversion to use in your campaign reporting and smart bidding. Calls and forms now both feed the same bidding optimization.

    One note on attribution windows: call tracking events fire when the call starts, not when it ends or converts. For businesses with long sales cycles, supplementing with an offline conversion upload at deal close gives a more accurate signal. See the lead source tracking guide for the full closed-loop setup.

    Connecting Call Tracking to Your CRM

    Phone calls need to land in your CRM with source attribution attached, the same way form submissions do. Most call tracking platforms support CRM integrations via native connectors or Zapier:

    • CallRail to HubSpot/Pipedrive/Close: native or Zapier integrations create a new contact and deal record when a call comes in, including call source, campaign, caller number, and duration. Duplicate logic (same caller number within X days = update existing, not create new) should be configured to avoid contact bloat.
    • Custom CRM or spreadsheet: CallRail’s webhook fires a POST request on each call with full call metadata as JSON. A lightweight Zapier or Make.com step can write this to a Google Sheet or custom CRM endpoint.

    The goal is the same as form attribution: every lead record should carry utm_source, utm_medium, utm_campaign, and utm_term so that when a deal closes, you can filter by source and see which channels produce revenue, not just calls.

    Installing Call Tracking on WordPress

    The cleanest installation path for WordPress is via Google Tag Manager:

    1. In your call tracking platform, copy the JavaScript snippet (for CallRail, it looks like a single script tag with your account token).
    2. In GTM, create a new Custom HTML tag and paste the snippet.
    3. Set the trigger to “All Pages.”
    4. Publish the container.
    5. Verify by loading your site with the GTM Preview pane open. Look for the call tracking script firing on pageview. Then check that phone numbers are swapping when you simulate different traffic sources using UTM parameters in the URL.

    If you are not using GTM, the snippet can also be added via the WPCode plugin or directly in your theme’s functions.php using wp_enqueue_script. GTM is preferred because it keeps the tracking layer out of your theme and survives theme updates.

    Common Mistakes to Avoid

    • Not testing number swap by source. Install the snippet, then visit your site directly (direct traffic), then with a Google Ads UTM in the URL, then with an organic search simulation. Confirm the number changes. A swap that is not working looks like it is working — until you notice form leads and call leads have identical attribution.
    • Using your main business number as a fallback in DNI. If the swap fails (JavaScript blocked, caching issue, slow load), you want the fallback to be a separate static tracking number, not your actual business number. A missed tracking event on your real number pollutes your direct traffic pool.
    • Ignoring call duration in conversion logic. A two-second call is not a lead. Set your GA4 conversion to only fire on calls over 60 or 90 seconds. Most call tracking platforms let you set this threshold; the shorter the minimum, the more noise in your conversion data.
    • Forgetting to exclude internal calls. If your team calls the tracked numbers for testing or internal routing, those sessions will fire conversion events. Add a filter for known internal numbers or your office IP range.

    What Good Call Attribution Data Looks Like

    Once call tracking is running alongside form tracking, your conversion reports tell a complete story:

    • Google Ads campaign reporting shows calls and forms in a single conversions column. Campaigns that were generating calls but zero forms are now correctly credited.
    • Your CRM has source data on every lead — phone or form — so close rate analysis by channel is possible without manual data entry.
    • Smart bidding in Google Ads is optimizing on all conversion types, not just the half that happen to submit a form.

    For most service businesses, adding call tracking to an existing form-attribution setup increases visible conversion volume by 30 to 80 percent — not because conversions increased, but because they were always happening and now they are counted.

    For a setup that handles UTM capture, form attribution, and call tracking integration in a single WordPress plugin — with closed-loop reporting that connects leads to revenue outcomes — Sales Provenance is built to cover every layer described here. Related reading: lead source tracking for WordPress, UTM parameter tracking on WordPress, and Google Ads conversion tracking for WordPress.

  • Marketing Attribution for Agencies: How to Prove Which Channels Are Working for Your Clients

    Your clients do not want channel reports. They want to know which channels are actually driving their business. The distinction matters more than it sounds: an agency that delivers traffic charts keeps the account as long as traffic is up. An agency that ties marketing activity to closed revenue keeps the account through hard quarters because the value is undeniable.

    Attribution is the mechanism that makes that conversation possible. This guide covers how marketing agencies can build attribution reporting for WordPress-based clients — what to track, where the data comes from, how to close the loop from ad spend to closed deal, and how to present it in a way clients actually understand.

    Why Agency Attribution Is Different From Standard Analytics

    Most analytics tools — GA4, platform dashboards, even Looker Studio reports — stop at the click or the session. They tell you how many people visited, which pages they viewed, and which campaigns drove traffic. That is useful. But it answers the wrong question for your clients.

    Your clients’ question is: “Where should I be spending my marketing budget to grow my business?” Answering that requires knowing not just which channels drive traffic, but which channels drive revenue. And for most service businesses and B2B companies, revenue happens offline — in a phone call, a proposal meeting, a signed contract. The gap between “user clicked an ad” and “client signed a deal” is where standard analytics fails and where attribution earns its keep.

    The three gaps agencies need to close

    • The form submission gap: a contact form fires a conversion in GA4, but the UTM source data is often lost or incorrect by the time it reaches the CRM. Without deliberate UTM capture in hidden form fields, lead source data in the CRM is unreliable.
    • The phone call gap: service businesses often get 30-60% of their leads by phone. If calls are not tracked by source, a significant portion of your client’s conversion volume is invisible to attribution.
    • The close rate gap: even if you know every lead source, you do not know which sources produce customers until you connect closed deal data back to the original campaign. A channel that drives 20 low-quality leads looks worse than one that drives 8 high-quality ones — until you look at close rates.

    The Attribution Stack That Works for Agency Clients

    Building accurate attribution for WordPress clients requires four connected layers. Each one is achievable without enterprise infrastructure.

    Layer 1: UTM capture in first-party cookies

    When a visitor arrives from a paid or tracked source, the UTM parameters land in the URL. A JavaScript snippet captures those values and stores them in first-party cookies before the visitor navigates anywhere. This preserves attribution across the session and across return visits.

    Critical detail: UTMs should be stored on first touch and not overwritten by a direct return visit. If someone clicks a Google Ad in week one and comes back via direct in week two, the original paid attribution should persist.

    Layer 2: UTM values passed through form submissions

    Contact forms (Gravity Forms, WPForms, CF7, and most others) should include hidden fields that read the UTM cookie values and include them in every submission. When a lead is created in the CRM or notification system, it carries source, medium, campaign, content, and term data.

    This is the step most WordPress sites are missing. Without it, lead source in the CRM is either blank or populated by whatever the rep entered manually — which is unreliable.

    Layer 3: Phone call attribution via dynamic number insertion

    DNI replaces the phone number shown on a webpage with a unique tracking number based on the visitor’s source. Someone who arrives from Google Ads sees a different number than someone who arrives from organic search or a Facebook ad. When they call, the tracking platform records which number they dialed and maps it back to the originating channel.

    CallRail is the standard tool for this. For agency clients, a basic DNI setup covers most use cases: one tracking number per significant traffic source (paid search, organic, paid social, email), with call recordings and source attribution feeding into a reporting dashboard.

    Layer 4: Closed deal data synced back to ad platforms

    Once you know which leads closed and at what value, you can sync that data back to Google Ads and Meta Ads as offline conversions. This closes two loops simultaneously: your internal reporting shows revenue by channel, and the ad platforms receive real conversion signals (closed deals vs. form submissions) that improve bidding algorithm performance.

    Google Ads offline conversion upload accepts a CSV with gclid and conversion value. Meta’s Conversions API accepts lead and purchase events with customer data for matching. Both can be automated — either through the ad platform’s native upload schedule or through a CRM integration.

    How to Structure Attribution Reporting for Agency Clients

    The goal is a report your clients can act on, not one they need a degree to read. Three levels of reporting cover most agency client needs:

    The executive summary: revenue by channel

    One table, updated monthly, showing for each channel: leads generated, leads closed, close rate, revenue attributed, and cost per closed deal (for paid channels). This is the report your client should be able to read in 60 seconds and use to make a budget decision.

    Channel Leads Closed Close Rate Revenue Cost/Close
    Google Ads (branded) 22 9 41% $47,200 $244
    Google Ads (non-brand) 31 6 19% $28,400 $621
    Organic search 14 5 36% $23,900 $0
    Referral 8 5 63% $31,000 $0

    This table tells a better story than any traffic chart. Your client sees immediately that referral has the highest close rate, branded search converts at 2x non-brand, and organic has meaningful cost-free contribution. Budget decisions become obvious.

    The campaign drill-down: cost efficiency by campaign

    For paid channels, a second level of reporting shows performance by campaign and ad group. Which campaigns are driving qualified leads? Which are generating volume that does not close? This is where campaign optimization decisions live.

    The keyword signal: search term close rate

    For Google Ads clients, connecting keyword data (via utm_term auto-populated from auto-tagging) to close rate data reveals which search queries precede closed business. A keyword generating 15 leads at 7% close rate should be paused or restructured. One generating 4 leads at 50% close rate deserves more budget. This analysis is only possible with proper attribution in place.

    The Agency Positioning Advantage

    Most agencies compete on deliverables: “we manage your Google Ads, we write your content, we handle your social.” Attribution reporting shifts the conversation to outcomes: “we can show you exactly which of your marketing dollars are generating revenue.”

    That positioning is harder to commoditize. An agency that delivers a monthly report showing $4.20 in closed revenue for every $1.00 in ad spend — with the receipts to back it up — is not competing on price. Agencies that only report traffic and impressions are always one underperforming quarter away from a churn conversation.

    The technical setup is not complicated. Most WordPress-based service businesses can have UTM capture, phone call attribution, and offline conversion sync running within a week. The barrier is knowing what to build and wiring the pieces together correctly.

    Tools and Implementation Options

    A few ways to build the attribution stack depending on your client’s existing setup and budget:

    • Custom UTM capture + hidden form fields: a lightweight custom implementation using first-party cookies and WPForms/Gravity Forms hidden fields. Works with any CRM or notification system. Good for clients who want to own their data without a new SaaS subscription.
    • CallRail for phone attribution: straightforward DNI setup, well-documented WordPress integration, integrates with GA4 and Google Ads. $45-$145/month depending on call volume. Worth it for any client getting 20+ calls per month.
    • HubSpot or other CRM with UTM field capture: if your client already uses HubSpot, Pipedrive, or Close, most support custom fields — map the UTM hidden fields to those fields in your form integration and attribution data flows in automatically.
    • Sales Provenance: a WordPress-native attribution layer that handles UTM capture, form submission enrichment, offline conversion sync to Google and Meta, and revenue attribution reporting in a single plugin. Built specifically for WordPress service businesses where the CRM dependency or data pipeline overhead of enterprise tools is not justified.

    For agencies managing multiple WordPress clients, a standardized attribution setup — whatever tools you choose — is worth systematizing. Build it once, document it, and deploy it across your client portfolio. It becomes a differentiator in your pitch and a retention driver once it is running.

    If you want to see how Sales Provenance fits into a WordPress-native attribution stack, the overview is here. Or read the companion guides: UTM parameter tracking on WordPress, Google Ads conversion tracking on WordPress, and closed-loop reporting for WordPress.

  • UTM Parameter Tracking on WordPress: How to Capture Lead Source Data and Keep It

    If you are running paid ads and relying on your ad platform’s dashboard to tell you which campaigns are generating leads, you are missing part of the picture. Ad platforms count clicks. UTM parameters let you count what happens after the click: form submissions, phone calls, and ultimately closed deals.

    This guide covers how UTM parameter tracking works on WordPress, how to pass UTM data through to your lead records, and how to use that data to make better decisions about where to spend your marketing budget.

    What UTM Parameters Are (and Why They Matter)

    UTM parameters are small tags you append to a URL. When someone clicks a link with UTM tags, those values land in the URL bar, and your tracking tools can read them. A tagged URL looks like this:

    https://example.com/landing-page/?utm_source=google&utm_medium=cpc&utm_campaign=summer-promo

    The five standard UTM parameters:

    • utm_source — where the traffic is coming from (google, facebook, email, newsletter)
    • utm_medium — the type of traffic (cpc, organic, social, email)
    • utm_campaign — the specific campaign name (summer-promo, brand-search, retargeting)
    • utm_content — the specific ad or link variant (useful for A/B testing)
    • utm_term — the keyword that triggered the ad (usually auto-populated by Google Ads)

    When these values are in the URL, GA4 can attribute the session to the right source. But GA4 only sees the session — it does not see the lead form submission in the context of the original source unless you capture and store the UTM data yourself.

    The Core Problem: UTMs Die When Someone Submits a Form

    Here is the gap that most WordPress sites have. A visitor arrives from a Google Ads click. Their URL has utm_source=google and utm_campaign=brand-search. They spend 3 minutes on your site, then submit a contact form. That form submission lands in your inbox or CRM with their name, email, and message — but no UTM data. You cannot tell whether this lead came from Google Ads, organic search, or a direct visit.

    Multiply this across 50 leads a month and you have a marketing team making budget decisions based on incomplete information.

    The solution is a two-step process: capture the UTM values when someone first lands, and carry them through to the form submission.

    How to Capture UTM Parameters in WordPress

    Step 1: Store UTMs in a first-party cookie on landing

    When a visitor arrives with UTM parameters in the URL, a small JavaScript snippet reads those values and saves them in a first-party cookie. That cookie persists for 30 days (or whatever window you set), so even if the visitor leaves and comes back without UTMs in the URL, you still have the original attribution data.

    The script runs on page load, checks for UTM values in the URL, and writes them to cookies only if they are present (so a returning visitor’s original attribution is not overwritten by a direct visit).

    // Capture UTMs on first touch, store in cookies for 30 days
    (function() {
      var params = new URLSearchParams(window.location.search);
      var utms = ['utm_source','utm_medium','utm_campaign','utm_content','utm_term'];
      utms.forEach(function(key) {
        var val = params.get(key);
        if (val) {
          document.cookie = key + '=' + encodeURIComponent(val) + '; path=/; max-age=2592000; SameSite=Lax';
        }
      });
    })();

    Add this to your WordPress site via a plugin like WPCode, through your theme’s functions.php, or through Google Tag Manager as a Custom HTML tag triggered on All Pages.

    Step 2: Pull UTM cookies into hidden form fields

    Your contact form (whether it is Gravity Forms, WPForms, Contact Form 7, or another plugin) should have hidden fields that read the UTM cookie values and include them in the submission. When someone submits the form, the UTM values travel with the lead data.

    Hidden field setup (in Gravity Forms as an example): add a Hidden field for each UTM parameter and set its default value to a JavaScript snippet that reads the corresponding cookie. Most form plugins support dynamic default values via a parameter name or a short code.

    The pattern: each hidden field reads its cookie value on page load and populates automatically. The user never sees these fields. The form submission includes both the visible data the user entered and the UTM attribution data you captured in the background.

    Passing UTM Data to Your CRM or Email Platform

    Once UTM values are in your form submission, they need to land somewhere useful. A few options:

    • Email notification: the simplest path — your form sends a notification email that includes all field values. The UTM fields show up alongside name, email, and message. Works immediately with no integration.
    • CRM via Zapier or native integration: map the UTM hidden fields to custom fields in your CRM. Now each deal record shows source, medium, and campaign. When a deal closes, you can trace it back to the originating campaign.
    • Google Sheet as a lead log: route form submissions to a sheet with columns for all UTM parameters plus timestamp, name, email, and message. A simple way to see lead source distribution without a CRM.

    What to Do With UTM Data Once You Have It

    UTM data becomes valuable when you connect it to outcomes, not just volume. A few questions it lets you answer:

    • Which campaigns generate the most leads? Basic source/medium/campaign breakdown. Google Ads vs. organic vs. Facebook vs. email.
    • Which campaigns close at the highest rate? If you track deal outcomes in a CRM, you can pull close rate by utm_campaign. A campaign generating 20 leads at 5% close rate is worth less than one generating 8 leads at 40% close rate.
    • Which keywords drive qualified leads vs. browsers? utm_term populated from Google Ads auto-tagging tells you exactly which search query preceded each lead. You can pause terms that generate volume but not closed business.
    • Which ad variants convert better? utm_content lets you tag individual ads or email links differently. If Ad A and Ad B send equal traffic but Ad A generates twice the form submissions, that is a clear signal.

    gclid vs. UTM: Which Should You Use?

    Google Ads appends a gclid (Google Click ID) to URLs automatically when auto-tagging is enabled. This is separate from UTM parameters and is used for Google’s internal attribution. You should use both.

    • UTM parameters give you source/medium/campaign data that works across platforms and integrates with GA4, your CRM, and any reporting tool you use.
    • gclid enables offline conversion upload to Google Ads — where you send lead outcome data back to Google so its algorithm can optimize toward closed deals, not just form submissions.

    The right setup captures both: UTMs go into cookies and then form fields for your own reporting, while gclid is captured separately for offline conversion sync back to Google Ads.

    Common WordPress Implementation Pitfalls

    • UTMs lost on redirect: if your landing page URL redirects (www to non-www, HTTP to HTTPS, or a tracking redirect), UTM parameters can be stripped. Audit your redirect chain and make sure parameters pass through.
    • Form caching stripping values: some caching plugins prevent JavaScript from running correctly on form pages, which means hidden fields do not populate. Add form pages to your cache exclusion list.
    • Cookie consent blocking the script: if you have a GDPR consent banner that delays non-essential scripts, UTM capture may not fire until after the user accepts. For most service businesses in the US this is not a live issue, but it is worth knowing.
    • Session-scoped storage losing first touch: using sessionStorage instead of cookies means attribution is lost if the user closes their browser and returns later. Use cookies with a 30-day window for first-touch attribution.
    • Overwriting first touch on return visits: your capture script should check whether a UTM cookie already exists before overwriting. If someone clicks an organic result in week 2, you do not want to overwrite the paid ad click from week 1 that actually drove the engagement.

    UTM Tracking as Part of a Larger Attribution Stack

    UTM tracking solves the first-party data capture problem: you own the lead source data, it lives in your CRM, and it survives the gap between ad click and form submission. But it is one layer of a full attribution stack.

    • UTMs tell you source, medium, and campaign at the session level
    • Offline conversion upload connects closed deals back to campaigns in Google and Meta
    • Phone call tracking via DNI (dynamic number insertion) captures attribution for callers who never submit a form
    • Revenue attribution pulls closed deal values back into your reporting so you see revenue by source, not just lead count

    For WordPress businesses running paid search and wanting a turnkey version of this stack — UTM capture, form submission tracking, offline conversion sync, and closed-loop revenue reporting — Sales Provenance is built to handle all of it natively, without requiring a data engineer or a CRM dependency.

    Related reading: Google Ads conversion tracking on WordPress — how to set up website conversions, capture gclid, and upload offline conversions. And closed-loop reporting for WordPress — connecting ad spend to closed deal value.