| utm_source | |
| utm_medium | cpc |
| utm_campaign | {campaignid} |
| utm_id | {campaignid} |
| utm_term | {keyword} |
| utm_content | {adgroupid} |
Google Ads is the umbrella that covers everything Google sells through its ad-buying interface — and that’s a lot. A single Google Ads account can run Search ads against query intent, Display banner ads on the GDN, YouTube video ads, Shopping ads pulled from Merchant Center, Performance Max campaigns that automate placement across all of those, Demand Gen campaigns on Discover and YouTube Shorts, plus App install/engagement campaigns. They share the same conversion-tracking infrastructure and the same UTM/tracking-template plumbing — but they support different subsets of ValueTrack macros, attribute differently, and report into different columns.
The convention utm_medium=cpc exists because Google’s URL builders treated cost-per-click as the default for paid Search. The {campaignid} and {adgroupid} macros set the convention that every other ad platform later imitated with their own dynamic-token syntax ({{campaign.name}} for Meta, __CAMPAIGN_NAME__ for TikTok, ${CAMPAIGN_NAME} for MediaGo). Get Google Ads’ UTM setup right and the rest of your stack tends to fall into place.
This page is the platform-side companion to the Google Analytics flagship. GA explains how UTMs land; this page explains how Google Ads sends them across all six campaign types — including the ValueTrack catalog, the five-level tracking-template hierarchy, the GCLID/GBRAID/WBRAID auto-tagging story, and the Conversion Goal trap that quietly inflates half the Conversions columns out there.
The recommended UTM template
| Parameter | Value | Why |
|---|---|---|
utm_source | google | Matches Google’s own source-category list → Paid Search / Paid Video / Paid Shopping in GA4. |
utm_medium | cpc | Hits the ^(.*cp.*|ppc|retargeting|paid.*)$ regex GA4 uses to classify paid channels. |
utm_campaign | {campaignid} | Numeric ID is stable across renames — name-based values break when you rename a campaign. |
utm_id | {campaignid} | Same as campaign. Powers GA4’s Campaign ID dimension and any cost-data import. |
utm_term | {keyword} | The keyword that triggered the ad. Blank on Display, AI Max, DSA, Performance Max. |
utm_content | {adgroupid} | Differentiates ad groups within the same campaign. |
This is the template the mini builder above hands users when they pick “Google Ads.” It produces clean, standards-only UTMs that work across every downstream tool.
ValueTrack: 40+ macros, not 6
Most third-party guides list six ValueTrack macros and stop. Google’s official ValueTrack reference documents over forty across nine categories. The ones you’ll actually use day-to-day:
The full token catalog is in the right rail and below — including the conditional macros ({ifsearch:} / {ifcontent:} / {ifmobile:}) that let one template adapt to network and device, the device codes (m/t/c), the network codes (g/s/d/ytv/x), and the URL-rewriting macros ({lpurl}, {escapedlpurl}, {lpurl+2} for redirect chains).
A few subtleties the headline list won’t tell you:
{lpurl}must be at the start of the tracking template, or it gets escaped. Google’s exact wording: “It will be escaped unless you put{lpurl}at the beginning.” Putting it anywhere else turns your final URL into a percent-encoded string that the destination server may not parse correctly.- The conditional macros are nest-friendly but
{ignore}isn’t. You can chain{ifsearch:cpc}{ifcontent:display}to set medium dynamically. You cannot embed{ignore}inside another macro — Google explicitly disallows{ifmobile:{ignore}}. - Several macros silently return blank on certain ad types.
{keyword}is blank on AI Max, DSA, Performance Max, and Display.{matchtype}is Search-only. If your DSA campaigns show emptyutm_term, that’s expected. - Demand Gen drops a lot of macros without erroring. Google’s reference explicitly states
{placement},{target},{keyword},{ifsearch:},{ifcontent:},{network}, and{targetid}are unsupported in Demand Gen. They don’t error — they output nothing.
Where to put the tracking template
Tracking templates can live at five different levels in Google Ads. The most specific one wins — anything you set at a deeper level overrides what’s above it.
- Account level —
Settings → Account Settings → Tracking. The base template. Applies to every campaign that doesn’t override. - Campaign level —
Campaign settings → Additional URL options. Overrides account-level for this campaign and everything underneath it. - Ad group level —
Ad group settings → Additional URL options. Overrides campaign-level for this ad group. - Ad or keyword level — set on individual ads (under the ad’s URL options) or on individual keywords (Search campaigns only). The most granular level Google supports for the standard tracking template field.
- Sitelink and asset level — sitelinks, callouts, and other assets each have their own URL options panel where you can override the inherited template. Useful when one sitelink should attribute to a different campaign in your downstream reporting than the parent ad.
The cascade is strict and silent: if you set the same template at the account level and at one keyword, only the keyword-level template fires for clicks on that keyword — and Google won’t warn you when you “update” the account template that your keyword-level overrides remain in place. Audit existing overrides before relying on a higher-level change.
For most accounts, set the template once at the account level and never touch the lower levels. The five-level capability exists for advanced use cases (different attribution per audience segment, separate tracking for branded keywords, sitelink-specific reporting) — not as a default authoring style.
The template itself is one URL with {lpurl} followed by your tracking parameters:
{lpurl}?utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_id={campaignid}&utm_term={keyword}&utm_content={adgroupid}
Google’s preview tool (the Test button next to the tracking template field) substitutes a real recent landing-page URL and shows you what users will actually be sent to. Use it before saving.
Parallel tracking
Since 2018 Google has used parallel tracking by default: the user is sent directly from the ad to your final URL while the tracking-template request fires in the background. Page loads are faster (no redirect-chain delay), but if your tracking template fails, the user doesn’t notice — they get to your page either way and your measurement system silently never receives the ping. Verify the template with the Test button instead of relying on user-facing failure to surface bad templates.
Auto-tagging: GCLID, GBRAID, WBRAID
Auto-tagging is on by default for new Google Ads accounts. When enabled, Google appends a click identifier to every outbound ad URL — but which identifier depends on the click context.
| Identifier | When it’s appended | What it tracks |
|---|---|---|
gclid | Standard web clicks where the user is identifiable (most non-iOS traffic). | Individual click — most precise attribution. |
gbraid | iOS app-to-app clicks (e.g. tap your ad in YouTube, open your iOS app via deep link). | App-to-app journey, aggregated. |
wbraid | iOS app-to-web, web-to-app, and Search clicks where ATT denied the user identifier. | Aggregated cohort, no individual tracking. |
The shift from a single GCLID to three identifiers happened in iOS 14.5 (2021) when Apple’s App Tracking Transparency made the unique-user GCLID unusable without consent. GBRAID and WBRAID measure performance in aggregate — Google can tell that some user from this click cohort converted, but not which one. Modeled conversion data fills the rest.
For the receiver-side picture — how GA4 reads these identifiers, when a stripped GCLID falls back to UTMs, why your Google Ads campaign sometimes appears as (direct)/(none) in reports — see GA4: GCLID auto-tagging vs manual UTMs.
Conversion Goals: primary vs secondary
Google Ads organises conversion tracking around three concepts: account-default goals, primary conversion actions, and secondary conversion actions. The classification controls which of your events show up in the headline Conversions column versus the more inclusive All Conversions column.
This isn’t strictly a UTM topic, but it’s the single biggest source of “my Google Ads numbers don’t match my actual sales” tickets — and the fix is platform-side, not URL-side.
The trap is straightforward: every primary conversion action sums into the Conversions column. So if you mark ViewContent, AddToCart, InitiateCheckout, AddPaymentInfo, and Purchase all as Primary, a single customer who walks the full funnel counts as five conversions. Smart Bidding then tries to optimise toward all five equally and dilutes the signal toward what actually pays the bills.
Limitations and gotchas
- The 1024-character URL limit is real. Long landing-page URLs plus a verbose tracking template can hit it on Display, where additional macros sometimes expand to longer strings. Trim what you don’t need rather than adding all 40+ macros “just in case.”
- Case sensitivity is real, even when Google’s regex is forgiving. GA4’s channel-grouping regex is case-insensitive in some places, but the Source/Medium dimensions preserve original case —
Googleandgooglecreate two rows in your reports. Lowercase everything. - Performance Max has limited GCLID support. Google’s own ValueTrack reference flags
{gclid}as having “Limited support in Performance Max.” If your PMax campaigns aren’t surfacing GCLID-based conversions, that’s expected. - Tracking-template overrides cascade silently. If you set the template at the account level and a campaign-level template already exists, the campaign-level one still applies. There’s no warning. Audit existing campaign-level templates before relying on an account-level change.
- The
{ignore}macro is final-URL-only. It marks a portion of the URL as tracking-only so Google doesn’t crawl it. It cannot be used in the tracking template itself, and it cannot be embedded inside another macro.
Verification
Three steps, in order:
- Click the Test button in the tracking-template settings. Google substitutes a real recent landing-page URL and shows you the resulting URL. If it doesn’t look right here, it never will live.
- Check the click in incognito. Run the ad query yourself, click your ad, and inspect the URL on the landing page. Confirm the UTMs landed AND that
gclid(orgbraid/wbraidon iOS) was appended by auto-tagging. - Verify in GA4 Realtime.
Reports → Realtimeshould show the session with the expected Source/Medium. If it shows(direct)/(none), the GCLID was stripped between the click and the landing page — see GA4: defensive UTMs for Google Ads for the fallback playbook.
Common problems
- My Google Ads campaign shows as
(direct)/(none)in GA4. GCLID is being stripped before it reaches your landing page. The most common culprits: link-shortener redirects, marketing-automation wrappers, AMP cache redirects, hash-routing apps that don’t trigger apage_view, or aggressive consent-mode scripts. Add defensive UTMs as a fallback (the manual UTMs only get used if GCLID is missing — see the GA flagship for the full mechanism). - My UTM template uses campaign names and they keep breaking. You’ve hardcoded
utm_campaign=summer_sale_2026instead ofutm_campaign={campaignid}. Names change when you rename campaigns; numeric IDs don’t. Always use{campaignid}forutm_campaignandutm_id. - My Demand Gen UTMs come back partially blank. Demand Gen doesn’t support
{keyword},{matchtype},{network},{targetid},{placement},{target}, or the{ifsearch:}/{ifcontent:}conditionals. Use a simpler template for Demand Gen campaigns. - My Conversions column is way higher than my actual sales. Multiple Primary conversion actions. Set Purchase as the only Primary; move everything else to Secondary.
- Enhanced Conversions warns about missing parameters. Google’s diagnostics flag this when first-party data (email, phone, address) isn’t reaching the conversion event. Email is the most important field. Make sure your conversion source (Shopify, ClickFunnels, your CRM) is sending the customer data through to Google Ads.
| Token | Description | Substituted at |
|---|---|---|
| {campaignid} | Numeric campaign ID. Stable across renames — recommended as utm_id. | Click time |
| {adgroupid} | Numeric ad group ID. | Click time |
| {creative} | Numeric ad creative ID. | Click time |
| {keyword} | The keyword that triggered the ad. Returns blank for AI Max, DSA, Performance Max, and Display. | Click time |
| {matchtype} | Keyword match type — 'e' (exact), 'p' (phrase), 'b' (broad), 'a' (AI Max). Search Network only. | Click time |
| {network} | Click source — 'g' (Google Search), 's' (search partners), 'd' (Display), 'ytv' (YouTube), 'x' (Performance Max). | Click time |
| {device} | Device type — 'm' (mobile), 't' (tablet), 'c' (computer). | Click time |
| {targetid} | Keyword, audience, product, or hotel-group target ID. Excludes affinity/in-market audiences. Not supported in Demand Gen. | Click time |
| {ifsearch:value} | Outputs the bracketed value only when the click came from Google Search. Pair with {ifcontent:} for one template that handles Search and Display. | Click time |
| {ifcontent:value} | Outputs the bracketed value only when the click came from the Display Network. | Click time |
| {ifmobile:value} | Outputs the bracketed value only when the click came from a mobile device. | Click time |
| {lpurl} | The final URL (your landing page). Required at the start of every tracking template. Auto-escaped unless placed at the very start. {escapedlpurl}, {lpurl+2}, {lpurl+3} variants exist for redirect chains. | Click time |
| {gclid} | Google Click Identifier — appended automatically by auto-tagging. Limited support in Performance Max. Don't add as a UTM parameter manually — auto-tagging handles it. | Click time |
