UTM Tracking for HubSpot Campaigns: How to Build and Validate Campaign Links

HubSpot email campaigns have a well-known UTM problem: HubSpot's default email tracking appends utm_source=hs_email to links — a non-standard source value that is specific to HubSpot's internal tracking system and does not match any canonical utm_source naming convention. In GA4, HubSpot's auto-tagged links appear as hs_email / email in the source/medium report rather than hubspot / email. This creates a second attribution row that does not consolidate with any other channel, makes cross-channel comparison harder, and signals to anyone reading your GA4 data that your UTM taxonomy is not standardised. Beyond the hs_email issue, HubSpot also appends its own hsa_* tracking parameters and its own utm_id values derived from HubSpot campaign IDs. The recommended approach is to override HubSpot's auto-UTM with custom parameters that match your taxonomy. This article covers the correct values, how to override HubSpot's auto-tagging, how to build consistent UTM links with mlz build, and how to validate destination URLs before each send.

Terminal showing mlz build command with utm_source=hubspot and utm_medium=email, a GA4 Email channel card, and the assembled tracked URL at the bottom.

The HubSpot hs_email auto-UTM problem

HubSpot's email marketing module automatically appends a set of tracking parameters to every link in your marketing emails. When HubSpot's built-in UTM tracking is enabled, the result looks like this:

HubSpot auto-generated UTM parameters (example)
# What HubSpot auto-appends to email links
https://example.com/landing
  ?utm_source=hs_email
  &utm_medium=email
  &utm_campaign=123456789
  &_hsenc=p2ANqtz--abc123
  &_hsmi=456789

The problems with HubSpot's auto-UTM output:

  • utm_source=hs_email: HubSpot's internal source identifier, not the platform name. In GA4, this creates a hs_email / email row rather than hubspot / email. If your team also has any direct HubSpot URLs or manually-tagged HubSpot links using utm_source=hubspot, they appear as a separate row — the same platform creates two different attribution sources in GA4.
  • Numeric utm_campaign: HubSpot uses its internal campaign ID (a numeric identifier) as the utm_campaign value. In GA4, your campaign reports show numbers like 123456789 rather than descriptive campaign names. You have to cross-reference HubSpot's campaign list to know what each number means.
  • _hsenc and _hsmi parameters: These are HubSpot's proprietary email tracking parameters for individual email opens and click attribution within HubSpot's own reporting dashboard. They are not UTM parameters and are not read by GA4. They appear in the URL and can make it harder to read the UTM parameters in browser address bars and analytics exports.
  • No utm_content: HubSpot's auto-UTM does not add a utm_content value, so you cannot distinguish between different CTAs or links within the same email.

The solution is to disable HubSpot's automatic UTM tagging for each email or workflow and provide your own custom UTM parameters in the link URLs before entering them in HubSpot's email editor.

The correct utm_source and utm_medium for HubSpot

For HubSpot email campaigns, use utm_source=hubspot and utm_medium=email. This is distinct from HubSpot's default utm_source=hs_email — the hubspot value identifies the platform clearly, matches your naming convention for other platforms, and produces a clean hubspot / email row in GA4's source/medium report.

HubSpot send type utm_source utm_medium GA4 default channel
Marketing email (newsletter) hubspot email Email
Workflow automation email hubspot email Email
Lead nurture sequence hubspot email Email
Transactional email hubspot email Email
A/B test email hubspot email Email

Some teams prefer utm_source=hs_email to maintain continuity with existing historical data already attributed that way in GA4. If your organisation has months or years of GA4 data using hs_email as the source and switching would create a discontinuity in trend reports, that is a valid reason to keep it — but the naming is still non-standard, and you should document the convention explicitly in your UTM taxonomy so future team members don't create a third source value by accident. The migration path is to note a date in your GA4 annotations when the source value changed.

For utm_campaign, use your own lowercase hyphen-separated campaign name — not HubSpot's numeric campaign ID. For example, q3-nurture-2026 instead of 123456789. This is the value visible in GA4 reports, so it should be human-readable and consistent with the naming convention you use for paid channels.

Building HubSpot campaign links with mlz build

mlz build generates the tracked URL, enforces lowercase normalisation, and stores the link for auditing. For a standard HubSpot marketing email with multiple CTAs:

mlz build — HubSpot newsletter primary CTA
# Primary CTA in a HubSpot marketing email
$ mlz build \
  --url "https://example.com/landing" \
  --source "hubspot" \
  --medium "email" \
  --campaign "q3-newsletter-2026" \
  --content "primary-cta"

{
  "tracked_url": "https://example.com/landing?utm_source=hubspot&utm_medium=email&utm_campaign=q3-newsletter-2026&utm_content=primary-cta",
  "params": {
    "utm_source": "hubspot",
    "utm_medium": "email",
    "utm_campaign": "q3-newsletter-2026",
    "utm_content": "primary-cta"
  },
  "link_id": "lnk_hs5m2k9r",
  "stored": true
}

Use utm_content to differentiate CTAs within the same email — primary-cta, secondary-cta, footer-link. For lead nurture sequences, the most common HubSpot email automation pattern, use a utm_content value that identifies the email number in the sequence:

mlz build — HubSpot nurture sequence email 3
# Email 3 in a 5-email HubSpot lead nurture workflow
$ mlz build \
  --url "https://example.com/case-study" \
  --source "hubspot" \
  --medium "email" \
  --campaign "q3-nurture-2026" \
  --content "email-3-cta"

{
  "tracked_url": "https://example.com/case-study?utm_source=hubspot&utm_medium=email&utm_campaign=q3-nurture-2026&utm_content=email-3-cta",
  "params": {
    "utm_source": "hubspot",
    "utm_medium": "email",
    "utm_campaign": "q3-nurture-2026",
    "utm_content": "email-3-cta"
  },
  "link_id": "lnk_hs7n4w2p",
  "stored": true
}

For HubSpot workflow automation emails, build all tracked URLs for the full sequence before entering them into the workflow editor. This lets you validate all destination URLs at once, store the full campaign's link set in MissingLinkz's link management, and paste the tracked_url values directly into HubSpot's email template editor with auto-UTM disabled. The MissingLinkz link list gives you an audit trail of every URL in the sequence — useful when a workflow has been running for months and you need to verify what UTM values were used for each step.

HubSpot for paid advertising: social and search campaign links

HubSpot is not only an email platform — many teams also use HubSpot to track paid social and search campaigns. HubSpot's Ads tool can auto-tag LinkedIn, Google Ads, and Facebook campaigns with HubSpot's own tracking parameters alongside (or instead of) UTM parameters. For paid channels, the approach differs from email:

HubSpot campaign type Recommended utm_source utm_medium Notes
Email (marketing, nurture) hubspot email Override HubSpot's auto-UTM
LinkedIn Ads (via HubSpot) linkedin cpc or social Use the platform as source, not hubspot
Google Ads (via HubSpot) google cpc Use the platform as source, not hubspot
Facebook Ads (via HubSpot) facebook cpc or social Use the platform as source, not hubspot

For paid channels managed through HubSpot's Ads tool, the traffic source should reflect the ad platform — not HubSpot. Using utm_source=hubspot for a LinkedIn campaign would merge paid LinkedIn clicks with HubSpot email clicks in the same GA4 source row, which destroys channel-level attribution. Only use utm_source=hubspot for emails sent from HubSpot's email marketing module.

HubSpot's Ads tool may also add its own tracking parameters alongside your UTM parameters. These are typically hsa_acc, hsa_cam, hsa_grp, and similar. These parameters are for HubSpot's internal paid attribution reporting and do not interfere with GA4 UTM attribution. You can leave them in place alongside your UTM parameters.

How to disable HubSpot's automatic UTM tagging

HubSpot's automatic UTM tracking is controlled in two places: the email settings at the account level and the individual campaign settings. To use custom UTM parameters:

  • Account-level default (HubSpot Marketing Hub): Go to Settings › Marketing › Email › Tracking. Under "Google Analytics tracking," you can toggle the default behaviour for new emails. Setting this to off means new campaigns start with auto-UTM disabled, but you must still add custom UTM parameters to your links manually.
  • Per-email campaign: In the email campaign editor, open the Settings tab and look for the "Tracking" or "Google Analytics" section. Disable the auto-UTM option for that specific email. This overrides the account-level default for a single email.
  • Workflow emails: In HubSpot's workflow editor, each email step that sends a marketing email uses the same email campaign editor. Open the email template for each step and disable auto-UTM in the template settings.

After disabling auto-UTM, paste the tracked_url values from mlz build directly into the link fields in HubSpot's email editor. HubSpot will still wrap the links in its own click-tracking redirect (using HubSpot's hs-email.com or similar domain), but the query string — including your UTM parameters — is preserved through that redirect. The UTM parameters reach your landing page intact, and GA4 reads them correctly.

To confirm everything is working, send yourself a test email from HubSpot, click the link, and check the URL in the browser address bar after the HubSpot redirect resolves. You should see your custom UTM parameters and no utm_source=hs_email or numeric utm_campaign values.

Validating destination URLs before sending

Like all email platforms, HubSpot sends cannot be recalled after delivery — a broken destination URL cannot be fixed for recipients who received the email. Run mlz build --validate before finalising each HubSpot campaign to confirm every destination URL resolves correctly, uses HTTPS, and returns a 200 status:

mlz build with --validate before HubSpot send
$ mlz build \
  --url "https://example.com/landing" \
  --source "hubspot" \
  --medium "email" \
  --campaign "q3-newsletter-2026" \
  --content "primary-cta" \
  --validate

{
  "tracked_url": "https://example.com/landing?utm_source=hubspot&utm_medium=email&utm_campaign=q3-newsletter-2026&utm_content=primary-cta",
  "validation": {
    "valid": true,
    "checks": [
      { "check": "url_format", "status": "pass", "message": "URL format is valid." },
      { "check": "ssl", "status": "pass", "message": "URL uses HTTPS." },
      { "check": "resolution", "status": "pass", "message": "Destination responded with 200.", "details": { "response_time_ms": 211 } },
      { "check": "redirects", "status": "pass", "message": "No redirects detected." }
    ]
  },
  "link_id": "lnk_hs5m2k9r",
  "stored": true
}

For HubSpot workflow automation sequences that run continuously (welcome series, onboarding flows, re-engagement workflows), it is worth re-validating destination URLs periodically — especially if the URLs point to landing pages that are updated, replaced, or temporarily taken offline during redesigns or A/B tests. An automation email that was correctly configured at workflow creation can silently send to a 404 page months later if the destination URL changed. Build a periodic audit step into your workflow maintenance process using mlz build --validate for each active workflow email.

HubSpot UTM tracking gotchas

hs_email in GA4 is not the same as hubspot
HubSpot's default utm_source=hs_email and a custom utm_source=hubspot create two separate rows in GA4's Traffic Acquisition source/medium report. If your team has previously used HubSpot's auto-UTM (creating hs_email / email rows) and you switch to custom parameters (creating hubspot / email rows), both rows will appear in GA4 for historical periods. This is expected — add a GA4 annotation for the date of the switch so future analysts can account for the source name change when comparing across time periods.
HubSpot's click tracking adds its own redirect hop
HubSpot wraps all links in marketing emails with its own click-tracking redirect. When a recipient clicks a link, the request goes first to HubSpot's tracking domain (which records the click for HubSpot's email analytics), then to your destination URL. HubSpot's redirect preserves the full query string including UTM parameters, so this hop is transparent to GA4. However, if your destination URL itself redirects — through a link shortener, a campaign landing page builder, or a CMS redirect rule — you may have a two or three-hop redirect chain. Check the full chain with mlz build --validate to confirm UTM parameters survive to the final destination.
HubSpot's numeric campaign IDs create unreadable GA4 reports
If you use HubSpot's default auto-UTM, the utm_campaign value in GA4 is a numeric HubSpot campaign ID like 123456789. This is technically valid but unreadable without cross-referencing HubSpot's campaign list. Anyone looking at your GA4 Traffic Acquisition report sees a list of numbers instead of campaign names. Using custom utm_campaign values with descriptive lowercase-hyphenated names (q3-newsletter-2026) makes GA4 reports directly readable without having to look up HubSpot campaign IDs.
hsa_* parameters from HubSpot Ads coexist with UTM parameters
When HubSpot's Ads tool is connected to LinkedIn, Google, or Facebook, it appends proprietary hsa_acc, hsa_cam, hsa_grp parameters alongside UTM parameters. These are for HubSpot's paid attribution dashboard and do not affect GA4 UTM attribution. GA4 reads only the five standard UTM parameters (utm_source, utm_medium, utm_campaign, utm_content, utm_term) and ignores unknown parameters like hsa_*. Do not remove the hsa_* parameters where HubSpot has appended them, as they are used by HubSpot's own reporting.
HubSpot and GA4 measure different events — both are correct
HubSpot's email analytics report opens, clicks, and contact-level engagement within HubSpot. GA4 reports sessions, conversions, and revenue attributable to clicks from HubSpot emails. These are complementary data points — a high HubSpot click rate with low GA4 sessions indicates a technical issue in the link chain (redirect stripping UTM parameters, GA4 tag not firing on the landing page, or HubSpot's click-tracking URL being blocked by certain email clients). Use both dashboards together for a complete picture, and validate the technical chain with mlz build --validate to confirm GA4 is receiving attribution data from HubSpot clicks.

HubSpot UTM naming conventions

Consistent naming across HubSpot and your other marketing channels is essential for clean GA4 attribution. Recommended conventions for HubSpot UTM parameters:

  • utm_source: hubspot — lowercase, for all emails sent from HubSpot's email marketing module
  • utm_medium: email — maps to GA4's default Email channel; use for marketing emails, automation emails, and transactional emails
  • utm_campaign: lowercase hyphen-separated descriptive name, e.g. q3-newsletter-2026, onboarding-series-2026, product-launch-may-2026
  • utm_content: CTA or email step identifier, e.g. primary-cta, secondary-cta, email-3-cta, footer-link, variant-a
  • utm_term: audience segment or list identifier if relevant, e.g. enterprise-prospects or trial-users

If you use multiple email and marketing automation platforms alongside HubSpot (e.g., Mailchimp for newsletters, HubSpot for nurture sequences, a transactional provider for receipts), keep utm_source as the platform identifier for each (hubspot, mailchimp, etc.) and use the same utm_campaign naming convention across all platforms. This lets you compare email channel performance across platforms in GA4 by filtering on utm_medium=email and grouping by source. See the UTM naming conventions guide for the cross-channel naming reference and the UTM tracking best practices guide for team-level governance recommendations.

FAQ

What is utm_source=hs_email and should I use it?
utm_source=hs_email is HubSpot's default auto-generated source value for emails sent through HubSpot's marketing email module. It is a proprietary HubSpot identifier, not a standard platform name. In GA4, it creates a hs_email / email row rather than hubspot / email. If your team is already using hs_email consistently across all HubSpot campaigns and want to maintain continuity with historical GA4 data, you can keep it — but document it explicitly in your UTM taxonomy so the convention is clear. For new implementations or teams migrating to better taxonomy, switch to utm_source=hubspot and note the changeover date in GA4 annotations.
How do I override HubSpot's automatic UTM tagging?
Disable HubSpot's "Google Analytics tracking" option in the email campaign's Settings tab. Once disabled, HubSpot sends your links exactly as entered — including any UTM parameters you added to the URL. Build your tracked URLs with mlz build and paste the tracked_url values directly into HubSpot's email editor link fields. Confirm the override is working by sending a test email, clicking a link, and checking that the URL in the browser address bar shows your custom UTM values — not hs_email or a numeric campaign ID.
Why does my HubSpot email traffic show differently in GA4 vs. HubSpot?
HubSpot and GA4 measure fundamentally different events. HubSpot counts email clicks as recorded by HubSpot's own click-tracking redirect. GA4 counts website sessions that arrive with UTM parameters. The two numbers are rarely identical: email clients sometimes prefetch links (inflating HubSpot click counts), some recipients click through on mobile with JavaScript disabled (so GA4 doesn't record the session), and UTM parameter stripping in a redirect chain can cause clicks to arrive without attribution. If the discrepancy is large, run mlz build --validate on your destination URLs to check the redirect chain.
Can I use mlz build for HubSpot workflow automation emails?
Yes. For HubSpot workflow automation sequences — welcome series, lead nurture flows, re-engagement campaigns — build all tracked URLs for the sequence upfront with mlz build, using consistent utm_campaign and sequential utm_content values per email step. Disable auto-UTM in each email template within the workflow. Paste the tracked_url values into the link fields of each email template in the workflow editor. Because automation emails run continuously over time, use stable campaign slugs that don't include time-sensitive dates — for example, welcome-series rather than welcome-series-q3-2026, since the same workflow may run through multiple quarters.
Do HubSpot's hsa_* parameters conflict with my UTM parameters?
No. HubSpot's hsa_acc, hsa_cam, hsa_grp, and similar parameters are HubSpot-proprietary tracking identifiers for its Ads attribution dashboard. GA4 reads only the five standard UTM parameters and ignores unknown parameters. You can have both utm_source=hubspot&utm_medium=email and hsa_acc=123 in the same URL — GA4 attributes the session based on the UTM parameters and ignores the hsa_* values entirely. Do not remove the hsa_* parameters where HubSpot has appended them, as they are needed for HubSpot's own paid attribution reporting.

Build HubSpot campaign links from the terminal

Pass --source "hubspot" --medium "email" to mlz build and get a normalised, validated URL ready to paste into HubSpot's email editor — no more hs_email or numeric campaign IDs in GA4. Add --content to distinguish CTAs within the same email, and --validate to confirm the destination resolves cleanly before your campaign goes live.

npm install -g missinglinkz

Free plan: 50 links/month. No credit card. See the UTM tracking for developers guide for the full programmatic workflow.