utm.new
Meta Ads logo
Multi-channel

Meta Ads UTM parameters

One Meta Ads account spans Facebook, Instagram, Messenger, and Audience Network — four surfaces, one URL parameters field at the ad level. Dynamic tokens like {{campaign.id}} fill UTMs at click time; fbclid handles platform-side attribution; the Conversions API plus the Pixel cover the post-iOS-14 measurement gap that pure client-side tracking can't.

Updated
Recommended UTM template
Open in builder →
utm_sourcefacebook
utm_mediumcpc
utm_campaign{{campaign.name}}
utm_id{{campaign.id}}
utm_term{{ad.name}}
utm_content{{adset.name}}

A Meta Ads account is one buying surface that fans out into four placement networks: Facebook, Instagram, Messenger, and Audience Network. The same campaign object can deliver into all four, and the same URL Parameters field on a given ad applies regardless of which placement actually rendered the impression.

That’s the conceptual handle. The mechanical reality is messier: Meta’s UTM tokens use double curly braces ({{campaign.id}}), which Google Ads and most other platforms don’t; placement dimensions return long underscore-separated strings; fbclid is the click identifier that’s easy to break by adding it manually; and the iOS 14.5 ATT change pushed the entire post-click measurement story onto a server-side track (Conversions API) most teams still haven’t fully wired up.

This page covers the URL Parameters field, the dynamic-token catalog, the fbclid story, the Pixel/CAPI handshake, and the small list of common ways the setup goes wrong.

ParameterValueWhy
utm_sourcefacebookGA4 default channel grouping classifies facebook as Paid Social. meta lands in Unassigned.
utm_mediumcpcMatches GA4’s paid-channel regex. paid-social also works but is less universal across analytics tools.
utm_campaign{{campaign.name}} or {{campaign.id}}Name is human-readable in reports; ID is rename-safe. Pick one and stick with it.
utm_id{{campaign.id}}Always the numeric ID. Powers GA4’s Campaign ID dimension and any cost-data import.
utm_term{{ad.name}}The most actionable level for paid social — creative-level performance is what you tune.
utm_content{{adset.name}}Audience differentiation. Add {{site_source_name}} here if you want to split FB vs IG.

This is the template the mini builder above hands users when they pick “Meta Ads.” It’s standards-only — no custom params — and it works across every downstream tool that reads utm_*.

Dynamic tokens

Meta calls them “dynamic URL parameters.” The catalog is small — about a dozen useful ones — but the syntax is what trips people up. Double curly braces, all lowercase, dot-separated path ({{campaign.id}} not {campaignid} not ${CAMPAIGN_ID}). Get the syntax wrong and the token outputs literally as {{campaign.id}} in your URLs.

A few practical points the headline list won’t tell you:

  • Names break, IDs don’t. {{campaign.name}} returns whatever the campaign is currently called. Rename the campaign tomorrow and every UTM-based join in your reporting silently desyncs against historical rows. The numeric ID variants ({{campaign.id}}, {{adset.id}}, {{ad.id}}) are stable forever — they outlive renames, restructures, and even archival.
  • {{placement}} is wordy. Returns strings like Facebook_Feed, Instagram_Stories, Instagram_Reels, Audience_Network_Native. Useful as a utm_content companion, but plan for the length — it can add 30+ characters to your URL.
  • {{site_source_name}} is the cheap split. Returns fb / ig / msg / an. If you want to break Facebook traffic from Instagram traffic in default GA4 reports without splitting your campaigns, drop this into utm_content.
  • No conditional macros. Meta has no equivalent of Google Ads’ {ifsearch:} / {ifmobile:}. If you need different UTMs per placement, you split the ad set rather than templating around it.

Where to put the URL parameters

Meta’s URL Parameters field lives at the ad level, in the ad’s tracking section (Ads Manager → edit ad → bottom of the page → URL parameters). There’s no campaign-level or ad-set-level template that cascades down. Every ad has its own field.

In practice this means: when you create a new ad, paste the template. When you duplicate an ad, the template duplicates with it. When you bulk-edit, you edit the URL Parameters field across many ads in one operation.

utm_source=facebook&utm_medium=cpc&utm_campaign={{campaign.name}}&utm_id={{campaign.id}}&utm_term={{ad.name}}&utm_content={{adset.name}}

Note: paste it without the leading ?. Meta appends the parameters after whatever query string the destination URL already has, joining with ? or & as needed.

When a user clicks a Meta ad, Meta appends fbclid=… to the destination URL. Your site’s Pixel reads the URL on landing, persists the value into the _fbc cookie (with a fb.<subdomain_index>.<creation_time>.<fbclid> format), and includes the cookie value in every subsequent Pixel event so Meta can join site-side conversions back to the click.

Three failure modes worth knowing:

  • Stripped fbclid. Link shorteners, marketing-automation wrappers, AMP cache, and aggressive consent-mode scripts can strip fbclid before it reaches your domain. Without it, the _fbc cookie isn’t created and Meta has no click identifier to join against. Result: Pixel events without click attribution, and your campaign data degrades.
  • Manual &fbclid=… in URL Parameters. Adding it manually creates duplicate fbclid params, the second of which is what gets persisted into the cookie — Meta then can’t match the cookie value back to the click that generated it. Don’t add fbclid to your UTM template.
  • First-party cookie blocked. Safari ITP and most ad-blockers drop the _fbc cookie or shorten its lifetime. The Conversions API (below) is the answer for this — it reads click metadata server-side where ITP doesn’t apply.

Pixel + Conversions API

Meta’s measurement story has two halves. The Pixel is the JavaScript tag on your site — fires events client-side, reads cookies, sends to Meta. Easy to install, blocked by everything from ad-blockers to Safari ITP to the user choosing No Tracking on iOS.

The Conversions API (CAPI) is the server-side complement. Same events, sent from your server (or your CDP, or a CAPI partner) to Meta’s Conversions API endpoint, with the _fbc value, hashed customer data, and an event_id. The Pixel and CAPI fire the same event — Meta deduplicates them by matching event_id + event_name.

For most advertisers in 2026 the practical setup is: Pixel for the 70% of clicks where it works, CAPI for the iOS-and-blocker tail it can’t reach, deduplication via event_id so you’re not double-counting. CAPI alone (without the Pixel) is technically possible but rare — the Pixel is what scrapes click metadata into the _fbc cookie that CAPI then ships to Meta.

For the receiver-side picture — how GA4 classifies utm_source=facebook, what happens when fbclid arrives without UTMs — see Google Analytics .

Limitations and gotchas

  • Double-curly syntax is Meta-specific. Don’t muscle-memory {campaign.id} from Google Ads — it outputs literally. Always {{campaign.id}} on Meta.
  • Case sensitivity matters. GA4 preserves source/medium case in dimensions. Facebook, facebook, and FACEBOOK create three rows. Lowercase everything.
  • No campaign-level URL template. Every ad has its own URL Parameters field. Use bulk edit when you need to update many at once; budget time for it.
  • fbclid won’t survive certain redirects. Test your redirect chain in incognito and confirm fbclid lands on the final destination domain.
  • {{site_source_name}} is not a substitute for splitting placements. If your conversion-rate gap between Facebook and Instagram is large, separate the ad sets — don’t just tag and hope the optimizer figures it out.

Verification

Three steps, in order:

  1. Preview the URL in Ads Manager — at the bottom of the ad-edit screen, Meta shows the resolved URL with tokens substituted against a sample value. If it doesn’t look right here, it never will live.
  2. Click your own ad in incognito. Run the targeting against yourself, click the ad, inspect the URL on your landing page. Confirm UTMs landed AND that fbclid was appended automatically.
  3. Verify in Events Manager. Events Manager → your Pixel → Test Events — fire a test event from your landing page and confirm it shows up with the click metadata Meta needs for attribution.

Common problems

  • My UTMs come out as literal {{campaign.id}} in URLs. Tokens were pasted into the destination URL field instead of the URL Parameters field. Move them.
  • My Meta campaign shows as (direct)/(none) in GA4. fbclid was stripped between click and landing. Common culprits: link shorteners, AMP cache, marketing-automation wrappers, hash-routing apps. Add the manual UTMs to the URL Parameters field as a fallback — they survive even when fbclid doesn’t.
  • My Pixel and CAPI events are double-counting in Events Manager. event_id mismatch between Pixel and CAPI. Both sides must send the same event_id for the same event. Check your CAPI implementation generates a stable ID and your Pixel reads the same value (via dataLayer or server-set cookie).
  • My iOS conversions look way lower than Android. Aggregated Event Measurement and shorter ATT-era attribution windows. Check your AEM priority ranking — Purchase should be rank 1 for ecommerce, not buried below upper-funnel events.
  • My UTM template uses campaign names and they keep breaking. You hardcoded utm_campaign=summer_sale_2026 instead of utm_campaign={{campaign.id}}. Names change when you rename; numeric IDs don’t.
Token Description Substituted at
{{campaign.id}}Numeric campaign ID.
Stable across renames — recommended as utm_id.
Click time
{{campaign.name}}Human-readable campaign name.
Renaming a campaign breaks downstream joins. Prefer the ID for utm_campaign too.
Click time
{{adset.id}}Numeric ad set ID.Click time
{{adset.name}}Ad set name.Click time
{{ad.id}}Numeric ad ID.Click time
{{ad.name}}Ad name.Click time
{{placement}}Where the ad rendered — e.g. Facebook_Feed, Instagram_Stories, Audience_Network_Native.
Returned as a long string with surface and slot separated by underscore.
Click time
{{site_source_name}}Two-letter source code — fb (Facebook), ig (Instagram), msg (Messenger), an (Audience Network).
Useful for splitting Facebook vs Instagram traffic when utm_source is shared.
Click time
fbclidFacebook Click Identifier — appended automatically by Meta when a user clicks an ad.
Don't add manually. Powers the _fbc cookie that links pixel events to the original click.
Click time

Frequently asked questions

Last reviewed
Should utm_source be 'facebook' or 'meta'?

Use facebook. GA4's default channel grouping classifies facebook as Paid Social out of the box; meta doesn't match any default rule and can land in Unassigned until you build a custom channel group. The platform's brand became Meta, but the source string convention has stayed facebook across the industry.

Where do I set the UTM template — campaign, ad set, or ad?

Ad level. Meta's URL Parameters field lives under the ad's tracking section, not at the campaign or ad set level. There's no inheritance and no five-level cascade like Google Ads has. If you run multiple ads in an ad set with the same UTM template, you copy-paste the template into each — or use Ads Manager's bulk edit to apply it to many ads at once.

Should I add fbclid as a UTM parameter manually?

No. Meta appends fbclid automatically to every outbound click on an ad. Adding &fbclid=… to the URL Parameters field creates duplicates and can break the _fbc cookie that links Pixel events back to the click. Same rule as Google Ads' GCLID: let the platform handle the click ID; use UTMs for everything downstream needs.

What's the difference between {{campaign.name}} and {{campaign.id}}?

{{campaign.id}} returns the numeric campaign ID — stable across renames. {{campaign.name}} returns the current name — changes the moment you rename the campaign and breaks any downstream report that joined on the old name. Use the ID as utm_id always; use the ID for utm_campaign too unless you have a strong reason to want the human-readable name in your reporting.

How do I split Facebook traffic from Instagram traffic in GA4?

Two paths. (1) Set utm_source=facebook for everything and add {{site_source_name}} to utm_content — you'll see fb vs ig as a content dimension. (2) Run separate ad sets per platform placement and hardcode utm_source=facebook or utm_source=instagram. Path 1 is more common because most ad sets target both placements; path 2 is cleaner if you genuinely want them as separate sources in default reports.

Why is my Pixel firing but my CAPI events look duplicated?

Pixel and Conversions API often double-fire — that's expected. Meta's event deduplication uses event_id + event_name matching to collapse them. If you're seeing duplicates in Events Manager, it usually means the Pixel and CAPI sides aren't sending the same event_id for the same event, so Meta can't recognise them as the same. Check that your CAPI integration generates a stable event_id per event and that the Pixel reads the same value via your dataLayer or server.

What's the iOS 14.5 / ATT impact on Meta Ads attribution?

Apple's App Tracking Transparency caps how much per-user data Meta can collect from iOS users who deny tracking, which is most of them. Meta's response: Aggregated Event Measurement — you pick up to 8 priority events per domain, and only the highest-priority event per session counts toward attribution. Practical impact: optimise for events further down the funnel (Purchase rather than ViewContent), accept that view-through windows are shorter (1 day on iOS post-ATT), and lean harder on CAPI for server-side event coverage where the iOS browser would have dropped the Pixel.

What's the URL Parameters field's character limit?

Meta hasn't published a hard public limit, but practical ceilings sit around the 1024-character total URL length. Long landing-page URLs plus six UTM params with name-style tokens ({{campaign.name}} etc.) can hit it on long-named campaigns. Switch to ID-style tokens ({{campaign.id}}, {{adset.id}}) to halve the substituted length.