> Site index: https://usehardal.com/llms.txt
> Every content route also serves markdown at <url>.md

# How to Create UTM Parameters: Best Practices and Templates

Create UTMs that survive Google Ads, HubSpot, Shopify, CRM, and warehouse reporting. Includes account-level and ecommerce templates.

Source: https://usehardal.com/blog/how-to-create-utm-parameters
Published: 2026-09-03
Updated: 2026-09-03
Author: Ecem Bircan
Category: Analytics

---

> **Quick answer:** Define one UTM vocabulary and apply it across every channel. Keep campaign names readable and campaign IDs immutable. For Google Ads, set the template once at account level. ValueTrack can then fill the campaign, ad group, creative, network, target, keyword, and match type on each click.

A URL builder can produce a valid link and still wreck your reporting. `Paid-Social`, `paid_social`, and `paidsocial` become three rows. A renamed campaign breaks a join based only on its name. A tracking template placed on one ad group silently overrides the account template.

Define the data contract before building the URL.

## How to create a UTM link in four steps

1. Start with the canonical destination URL. Remove old tracking parameters and confirm the page loads.
2. Select `utm_source` and `utm_medium` from an approved list. Do not invent a new spelling for each campaign.
3. Add a readable `utm_campaign` and a stable `utm_id`. Use `utm_term` for targeting and `utm_content` for the creative or link placement when those details matter.
4. Encode the URL, click it, and confirm the parameters survive every redirect, locale change, form, and checkout step.

[Google's Campaign URL Builder](https://ga-dev-tools.google/campaign-url-builder/) can assemble and encode a one-off link. The naming registry is what keeps the next hundred links consistent.

## Use one UTM structure

Google Analytics recognizes more campaign parameters than the five fields in most URL builders. [Google's current URL builder documentation](https://support.google.com/analytics/answer/10917952) recommends setting all relevant parameters, especially source, medium, campaign, campaign ID, and source platform.

Use these fields consistently:

| Parameter | What it should identify | Rule | Example |
| --- | --- | --- | --- |
| `utm_source` | The platform or referrer | Use one approved value per platform | `adwords`, `linkedin`, `customer_newsletter` |
| `utm_medium` | The marketing channel | Use a short controlled list | `ppc`, `paid_social`, `email`, `referral` |
| `utm_campaign` | The readable campaign name | Match the name used in the ad platform and reporting plan | `emea_enterprise_demo_q4_2026` |
| `utm_id` | The immutable campaign ID | Use the platform ID when available | `21483765091` |
| `utm_term` | The keyword or targeting value | Populate dynamically on paid search | `server-side+tracking` |
| `utm_content` | The creative, ad, or link placement | Prefer a stable ID, or a governed creative name | `video_testimonial_v2` |
| `utm_source_platform` | The platform that managed the traffic | Add it when your GA4 reporting uses the dimension | `Google Ads` |

Tag every campaign with the first three fields. Add `utm_id` because campaign names change while platform IDs usually stay fixed. GA4 can also use it to join campaign cost data.

`utm_term` and `utm_content` answer narrower questions. Use term for the targeting that caused the click. Use content for the thing the person clicked. Do not stuff region, audience, funnel stage, keyword, and creative into `utm_campaign` when each already has a field.

## Set naming rules before anyone builds a link

UTM values are case-sensitive. Google Analytics treats `Google`, `google`, and `GOOGLE` as different values. Lowercase everything you control and pick one separator. Underscores are easy to scan in exports and SQL.

A practical campaign pattern is:

```text
region_offer_audience_period
```

For example:

```text
emea_server_side_tracking_enterprise_q4_2026
```

Keep source and medium out of that value. They already have their own columns. If the same initiative runs on Google Ads and LinkedIn, the campaign name can stay the same while `utm_source`, `utm_medium`, and `utm_id` identify each buy.

Maintain a short registry that every marketer and agency can see:

| Field | Approved values or format |
| --- | --- |
| Source | `adwords`, `facebook`, `instagram`, `linkedin`, `bing`, `customer_newsletter` |
| Medium | `ppc`, `paid_social`, `email`, `affiliate`, `referral`, `qr` |
| Campaign | `region_offer_audience_period` |
| Content | Stable creative ID or `format_message_version` |
| Term | Platform keyword or targeting token |

Choose `google` and `cpc` if GA4 manual campaign reporting owns your naming model. Choose `adwords` and `ppc` if HubSpot owns paid-ad attribution. With Google Ads auto-tagging enabled, GA4 can still report Google Ads traffic as `google/cpc` while HubSpot retains its own values. Randomly switching conventions across manual links will still split the reports that read those UTMs directly.

Here is a manually tagged link built from that contract:

```text
https://example.com/demo?utm_source=linkedin&utm_medium=paid_social&utm_campaign=emea_server_side_tracking_enterprise_q4_2026&utm_id=li_48291&utm_content=founder_video_v2
```

Encode spaces and special characters before publishing. Never place email addresses, names, phone numbers, or other personal data in a UTM value. URLs appear in browser history, analytics payloads, logs, screenshots, and referrer data.

## UTM templates for ecommerce, SaaS, lifecycle, and partners

The same UTM fields feed different revenue records. Ecommerce joins a click to an order. SaaS carries it into an account and opportunity. Lifecycle campaigns end at a purchase, renewal, or activation.

| Version | Source and medium examples | Campaign format | Content or term | Conversion join |
| --- | --- | --- | --- | --- |
| Ecommerce and DTC | `google/cpc`, `instagram/paid_social`, `klaviyo/email` | `market_promotion_audience_period` | Creative, ad, link block, or keyword | Session to order ID, revenue, and line items |
| B2B and SaaS | `linkedin/paid_social`, `google/cpc`, `partner/referral` | `region_offer_segment_period` | Ad, message, keyword, or governed audience | Session to contact, account, and opportunity |
| Lifecycle | `klaviyo/email`, `braze/push`, `attentive/sms` | `program_message_period` | Link position or test variation | Known customer or user to purchase, renewal, or activation |
| Partners and creators | `creator_slug/affiliate`, `partner_name/referral` | `promotion_audience_period` | Placement, post, or promo-code ID | Partner ID to order or qualified lead |
| Events and QR codes | `event_slug/qr`, `store_slug/qr` | `city_event_period` | Booth, screen, badge, or handout | Scan to registration, store visit, or lead |

Keep one source and medium registry across every version. Change the campaign pattern only when the business question changes.

### Ecommerce and Shopify UTM template

For ecommerce, tag the channel, promotion, audience, and creative. Put catalog data in separate custom parameters so a product rename does not create a new campaign row.

Paid social example:

```text
https://shop.example.com/collections/sale?utm_source=instagram&utm_medium=paid_social&utm_campaign=de_bfcm_prospecting_2026&utm_id=2386123456789&utm_content=ugc_hook_03
```

Lifecycle email example:

```text
https://shop.example.com/products/rain-jacket?utm_source=klaviyo&utm_medium=email&utm_campaign=winback_90d_2026_09&utm_id=msg_01k4c2f8&utm_content=hero_cta_a
```

For Google Shopping or Performance Max, use this Final URL suffix when HubSpot is not managing the URL:

```text
utm_source=google&utm_medium=cpc&utm_campaign={_utmcampaign}&utm_id={campaignid}&utm_content={creative}&asset_group_id={assetgroupid}&product_id={product_id}&product_country={product_country}&product_language={product_language}
```

If HubSpot is active, append only the `asset_group_id` and product fields to the HubSpot template later in this guide. Do not install a second set of UTMs.

Google fully supports `{assetgroupid}` in Performance Max. Product fields have limited support because they apply only to eligible shopping inventory. In [Google's ValueTrack reference](https://support.google.com/google-ads/answer/6305348), `{product_id}` is the Merchant Center ID of the product featured in the clicked ad. Purchased products come from the order's line items, joined back to the session.

[Shopify order conversion details](https://help.shopify.com/en/manual/fulfillment/managing-orders/analytics/conversion-summary) can show the UTM parameters attached to a customer visit. Shopify Analytics also exposes [order UTM source, medium, campaign, content, and term dimensions](https://help.shopify.com/en/manual/reports-and-analytics/shopify-reports/report-types/analytics-fields). Cookie restrictions and headless storefronts can limit the customer journey. Run a test order, then compare Shopify's record with GA4 or your first-party event stream.

### B2B and SaaS UTM template

Carry `utm_id` from the anonymous session into the form submission, then onto the account or opportunity. A closed-won report can group revenue by that stable ID even after someone renames the campaign.

Keep company name, job title, email address, and account ID out of the URL. Those belong in the CRM record after the person submits the form.

### Lifecycle email and SMS UTM template

Set `utm_source` to the sending platform, `utm_medium` to the message type, `utm_campaign` to the campaign or flow, and `utm_id` to the message ID. Reserve `utm_content` for the link block or test variation.

Klaviyo can apply defaults across email, SMS, WhatsApp, and push under **Settings > Other > UTM tracking**. Its [current UTM guide](https://help.klaviyo.com/hc/en-us/articles/115005247808) recommends the dynamic message type for `utm_medium` when an account uses several channels. Keep list and segment names out of `utm_source`; those values fragment the channel dimension and can expose internal audience labels.

### Partner, creator, and offline UTM template

Give every partner or creator a stable source slug, then record the relationship type in `utm_medium`, the shared promotion in `utm_campaign`, and the placement in `utm_content`. Add a separate partner ID when names may change. For QR codes, use a stable store or event source and record the physical placement, such as `checkout_counter` or `booth_banner`, in content.

```text
https://shop.example.com/collections/fall?utm_source=creator_482&utm_medium=affiliate&utm_campaign=fall_launch_2026&utm_content=youtube_description
```

## Why the HubSpot template is the industry-standard baseline

There is no formal standard for a complete paid-media tracking template. For teams using HubSpot, its template is the industry-standard baseline for Google Ads plus CRM attribution. It combines readable UTM fields with `hsa_*` fields that preserve the Google Ads entities behind a click.

[HubSpot documents the exact Google Ads mapping](https://knowledge.hubspot.com/ads/track-and-report-on-google-ads-in-hubspot): campaign, ad group, ad, network, target, keyword, match type, account, and template version. HubSpot uses those values to connect an ad click to a contact. GA4 and other analytics tools read the UTM fields. A warehouse can retain both.

HubSpot owns the `hsa_*` fields. Some values appear twice because HubSpot and analytics tools read separate keys:

- `utm_id={campaignid}` gives analytics and cost-import workflows a stable campaign key.
- `hsa_cam={campaignid}` gives HubSpot the same campaign key in its own schema.
- `utm_term={keyword}` fills the standard paid-keyword dimension.
- `hsa_kw={keyword}` preserves the keyword for HubSpot attribution.

Keep `hsa_ver=3`. It identifies the HubSpot template version and appears in HubSpot's current documented template.

## Ready-to-paste Google Ads and HubSpot template

Use this account-level tracking template. Replace `YOUR_GOOGLE_ADS_CUSTOMER_ID` with the account ID, without dashes.

```text
{lpurl}?utm_term={keyword}&utm_campaign={_utmcampaign}&utm_source=adwords&utm_medium=ppc&utm_id={campaignid}&hsa_acc=YOUR_GOOGLE_ADS_CUSTOMER_ID&hsa_cam={campaignid}&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3
```

This version starts with HubSpot's documented template and adds `utm_id={campaignid}`. Google recommends campaign ID as a standard manual campaign field, and the immutable ID is safer for joins than a campaign name alone.

The dynamic values come from [Google Ads ValueTrack parameters](https://support.google.com/google-ads/answer/2375447):

| Token | Value written after the click |
| --- | --- |
| `{lpurl}` | The ad's final landing-page URL |
| `{campaignid}` | Google Ads campaign ID |
| `{adgroupid}` | Ad group ID |
| `{creative}` | Ad or creative ID |
| `{network}` | The network that produced the click |
| `{targetid}` | Keyword, audience, product, dynamic target, or keywordless target ID |
| `{keyword}` | The matched keyword when one exists |
| `{matchtype}` | `e`, `p`, or `b` for exact, phrase, or broad match, and `a` for an AI Max keywordless match |
| `{_utmcampaign}` | A custom parameter containing the readable campaign name |

Google inserts an empty value when a token does not apply. Performance Max, Display, and keywordless AI Max traffic may have no keyword. Google specifically recommends reading `{matchtype}`, `{targetid}`, and `{keyword}` together for AI Max. Treat an empty `utm_term` as expected on those clicks.

`{keyword}` records the matched account keyword. Find the person's query in the Google Ads search terms report.

## Set up the template once at Google Ads account level

Pick one system to manage the template.

- If HubSpot is connected, turn on **Auto tracking** under **Marketing > Ads** and let HubSpot apply its campaign-level template.
- If you manage the template manually, turn off HubSpot auto-tracking first. Otherwise, HubSpot can overwrite campaign-level parameters during its next sync.

For the manual account-level setup:

1. Keep Google Ads auto-tagging enabled. The `gclid`, `gbraid`, and `wbraid` identifiers support Google Ads measurement and linked GA4 features. UTMs serve the CRM, warehouse, and cross-channel reporting layer beside them. [Google documents how manual parameters and auto-tagging work together](https://support.google.com/analytics/answer/15612152).
2. Open **Admin > Account settings > Tracking** in Google Ads.
3. Paste the full string into **Tracking template**.
4. Replace `YOUR_GOOGLE_ADS_CUSTOMER_ID` with the ten-digit customer ID and remove its dashes.
5. Open each campaign's **Settings > Additional settings > Campaign URL options**. Add the custom parameter name `_utmcampaign` and set its value to the exact governed campaign name.
6. Click **Test**, confirm the landing page loads, and save.

Google does not offer a built-in `{campaignname}` ValueTrack token. `_utmcampaign` is a custom parameter. HubSpot creates it when auto-tracking is active. Manual accounts must set it per campaign, ideally through Google Ads Editor or a bulk workflow. [Google's custom-parameter guide](https://support.google.com/google-ads/answer/6325879) confirms that custom parameters cannot be defined at account level.

Before saving, inspect campaign, ad group, ad, and keyword URL options. Google Ads uses the most specific tracking template it finds. The order is keyword, ad, ad group, campaign, then account. A forgotten keyword-level template can bypass a perfect account-level setup. The **Tracking template source** column shows which level won. [Google documents the hierarchy here](https://support.google.com/google-ads/answer/7197008).

Google says tracking-template changes can take 24 to 48 hours to reach ad serving. The built-in test checks URL construction immediately. Run a controlled live click after the change has propagated.

## Use Final URL suffix when HubSpot is not involved

For an account that has no HubSpot or third-party click tracker, Google's **Final URL suffix** is cleaner for parameters that only need to reach the landing page. Enter the fields without `{lpurl}?`:

```text
utm_source=google&utm_medium=cpc&utm_campaign={_utmcampaign}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}
```

Add it under **Admin > Account settings > Tracking > Final URL suffix**. Google appends the suffix to each final URL and handles whether the landing page already contains a question mark. [Google documents account-level Final URL suffix setup](https://support.google.com/google-ads/answer/9054021).

Use HubSpot's tracking template when HubSpot needs the `hsa_*` contract. Use Final URL suffix for a simpler Google Ads and GA4 setup. Do not install both versions because that duplicates the UTM keys.

## Test the full attribution path

The Google Ads **Test** button proves only that the URL resolves. Verify separately that analytics, CRM, and backend systems retained the values.

Check one controlled click from end to end:

1. Open the final landing URL and confirm it returns a successful page without an unexpected redirect.
2. Inspect the address bar or network request. Confirm each ValueTrack token became a real value and no `{braces}` remain.
3. Confirm the landing page keeps the UTMs and Google click ID through HTTPS, locale, authentication, and checkout redirects.
4. Verify the session in GA4 or [Hardal Events and Sessions](https://usehardal.com/blog/hardal-events-and-sessions). Check source, medium, campaign, and the original landing URL.
5. Submit a test lead. Confirm the CRM record contains the campaign name, campaign ID, and available click ID.
6. Complete a test conversion and confirm the same attribution fields reach the order, opportunity, or backend event.

HubSpot requires the final, non-shortened destination URL because redirects and shorteners can strip its tracking parameters. Test the URL a person reaches after every redirect.

## UTM mistakes that split or erase data

| Mistake | Result | Fix |
| --- | --- | --- |
| Switching between `google/cpc` and `adwords/ppc` | One platform appears under multiple source and medium rows | Choose the convention your primary reporting system expects |
| Using campaign name without `utm_id` | Renames break warehouse and cost joins | Store the readable name and immutable ID |
| Typing every ad URL by hand | Spelling, case, and encoding drift | Use dynamic parameters and a governed builder |
| Adding a lower-level Google Ads template | The account template stops applying to that branch | Remove the override or reproduce the full template there |
| Expecting `{keyword}` on every campaign type | Blank term values look like tracking failures | Treat term as optional and use target, creative, and campaign IDs |
| Tagging internal website links | A new campaign source replaces the visitor's original acquisition context | Reserve UTMs for links entering the site |
| Putting customer data in UTM values | Personal data spreads through URLs and logs | Use anonymous campaign metadata only |
| Dropping parameters during a redirect | Analytics and CRM lose the acquisition record | Preserve the full query string and test every hop |

UTMs describe the click. To attribute a conversion, your site must capture the parameters under the permitted consent state and join them to a lead, order, or account. A server-side session preserves that record after the landing page is gone. [Hardal Analytics](https://usehardal.com/analytics) keeps campaign fields beside the events and sessions they produced.

Start with the naming registry, install the account-level template, and test one real lead before the next campaign spends money.
