Free tool
Meta Ads UTM Builder
Build a tagged destination URL for a Facebook or Instagram ad, including Meta's dynamic URL parameters, and get the exact string the ad-level URL parameters field expects.
Updated August 2026 · AdPlay.ai Team
A UTM-tagged Meta ad URL carries five parameters: utm_source, utm_medium, utm_campaign, utm_content and an optional utm_term. The cleanest setup puts them in Ads Manager's ad-level URL parameters field, under Ad then Links then Advanced options, as a query string with no question mark in front, and uses Meta's dynamic parameters so values fill themselves at click time: utm_source={{site_source_name}}, utm_campaign={{campaign.name}}, utm_content={{ad.name}}. Keep utm_medium static so the traffic files under Paid Social. UTM values are case-sensitive, so Facebook and facebook are counted separately, which is why a lowercase convention is worth enforcing before you have a year of mixed data.
Tracking a Meta ad is two decisions and a lot of typing. The decisions are which parameters carry which meaning and whether you let Meta fill them in for you. The typing is what goes wrong: a capital letter, a stray space, a second question mark, and a week of data quietly reports under the wrong channel. Set the fields below once and paste the result into Ads Manager.
The page the ad sends people to, before any tracking is added.
Where the click came from.
The channel. Keep this static so the traffic files under Paid Social.
Which campaign. The dynamic token carries the name you typed in Ads Manager.
Which creative. This is the field that tells you which angle won.
Optional. Commonly the placement.
Paste this into the ad-level URL parameters field
In Ads Manager, under Ad, then Links, then Advanced options. This field takes the parameters on their own, with no question mark in front.
utm_source={{site_source_name}}&utm_medium=paid-social&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&utm_term={{placement}}
The whole tagged URL, for testing
Load this in a browser to confirm it lands on the right page. Dynamic tokens stay as literal text until a real click fills them.
https://example.com.my/collections/best-sellers?utm_source={{site_source_name}}&utm_medium=paid-social&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&utm_term={{placement}}
Worth checking before you launch
- {{site_source_name}} and {{placement}} can come back empty under some Advantage+ configurations. Check live reporting after launch rather than assuming they resolved.
| Token | What Meta fills in |
|---|---|
| {{site_source_name}} | The platform, as a short code: fb, ig, msg or an Can return empty under some Advantage+ configurations. |
| {{placement}} | The placement, such as feed or stories Can return empty under some Advantage+ configurations. |
| {{campaign.name}} | The campaign name, exactly as you typed it |
| {{campaign.id}} | The campaign numeric ID |
| {{adset.name}} | The ad set name |
| {{adset.id}} | The ad set numeric ID |
| {{ad.name}} | The ad name, which is why ad naming is a tracking decision |
| {{ad.id}} | The ad numeric ID |
Everything here runs in your browser. Nothing you type is sent anywhere or stored.
Put the parameters in the ad, not in the link
Ads Manager has a field made for this. Open the ad, scroll to Links, expand Advanced options, and you will find URL parameters. It takes the query string on its own, with no question mark in front, and Meta joins it to the destination URL when the ad runs. That is the top output in the builder above, which is why it is separated from the full URL rather than left for you to trim.
Editing the destination URL directly works too, and it is worse for a reason that shows up months later. A tagged destination URL is hard to read at a glance, hard to audit across a hundred ads, and easy to break when someone copies it into a new ad and keeps only half the string. Keeping the link clean and the parameters in their own field means you can change tracking without touching the destination, and change the destination without re-tagging.
The second output, the whole tagged URL, exists for testing. Load it in a browser before you spend anything and confirm three things: it reaches the page you meant, there is exactly one question mark in the address, and no double-brace token is sitting there as literal text on a value you meant to be static.
Let Meta fill in what it already knows
Meta publishes eight dynamic URL parameters, double-brace tokens it substitutes at click time. They are listed in the builder with what each one fills in. The practical effect is that tracking stops being per-ad work: set utm_campaign={{campaign.name}} and utm_content={{ad.name}} once, and every ad you launch afterwards arrives in analytics correctly labelled without anyone remembering to do anything.
That convenience has a consequence worth planning for. Because the tokens inherit your names, the naming convention inside Ads Manager becomes your tracking convention by proxy. An ad called "Final FINAL v3 (use this one)" lands in your reports as exactly that string, spaces and capitals included. The cheapest fix is upstream: name ads the way you want them to read in analytics, lowercase and hyphenated and descriptive of the angle.
Two of the eight need watching. {{site_source_name}} and {{placement}} can come back empty under some Advantage+ configurations, where Meta's automation abstracts the placement away. The builder flags it when you use either. It is not a reason to avoid them, only a reason to check live reporting after launch rather than assuming the value resolved.
The four things that quietly break the data
Case is the first and the most expensive. Google confirms UTM values are case-sensitive, so Facebook and facebook are two different sources and one campaign becomes two rows with half the numbers each. Nothing warns you. By the time it is obvious you have a quarter of split history that cannot be merged retroactively.
Spaces are the second. A space survives into the URL as %20 and reads that way in every report, so a campaign named with spaces arrives looking like a bug. Hyphens instead, everywhere, and the same rule applied to ad names since the dynamic tokens carry them through.
The third is a malformed URL: a second question mark, or parameters placed after a fragment. A URL takes exactly one question mark and everything after it joins with an ampersand, and anything sitting after a hash is invisible to analytics. The builder checks both.
The fourth only bites campaigns using dynamic tokens: shortening the finished link. A shortener resolves the string as text, so the tokens ship unfilled and every click arrives untagged. Shorten the static destination and let Ads Manager append the parameters to it.
By the numbers
Frequently asked questions
Where do I put UTM parameters on a Facebook ad?
In Ads Manager, open the ad, scroll to Links and expand Advanced options, then paste the parameters into the URL parameters field. That field takes the query string on its own, with no question mark in front of it, and Meta joins it to whatever destination URL the ad already carries. Setting it there rather than editing the destination URL keeps the link clean and makes the tagging easy to audit later.
What are Meta's dynamic URL parameters?
They are double-brace tokens Meta substitutes at click time, so no value has to be typed per ad. The eight confirmed ones are {{site_source_name}}, {{placement}}, {{campaign.id}}, {{campaign.name}}, {{adset.id}}, {{adset.name}}, {{ad.id}} and {{ad.name}}. Set them once and every ad inherits correctly named tracking without anyone touching an ad again.
Why is my utm_content coming back empty?
Two of the eight tokens, {{site_source_name}} and {{placement}}, can return empty under some Advantage+ configurations where Meta's automation abstracts the placement away. {{ad.name}} is more reliable, but it inherits whatever you called the ad, so an unnamed or oddly named ad produces an unhelpful value. Check live reporting after launch rather than assuming a token resolved.
Should utm_source be facebook or {{site_source_name}}?
Either is defensible and the choice matters more than the answer. The token returns a short code, fb for Facebook, ig for Instagram, msg for Messenger and an for Audience Network, which is precise but reads as jargon in a report. A static value of facebook is readable but merges Instagram traffic into it. Pick one, apply it everywhere, and do not change it midway through a year.
Does capitalisation matter in UTM values?
Yes, and it is the most common way a report quietly splits in two. Google confirms UTM values are case-sensitive, so Facebook and facebook become separate sources and your campaign appears twice with half the numbers each. Lowercase everything, hyphenate instead of using spaces, and enforce it at the ad-naming stage since {{ad.name}} carries your naming convention straight into analytics.
Can I shorten a link that contains dynamic parameters?
Not after the parameters are attached. A shortener resolves the string as literal text, so the double-brace tokens ship unfilled and every click arrives untagged. If you need a short link, shorten the static destination URL and let Ads Manager append the parameters to it.
How do I check the tagging worked?
Static values can be checked before you spend: load the full tagged URL in a browser, confirm it reaches the right page, and confirm there is exactly one question mark and no unfilled token sitting in the address. Dynamic tokens only resolve on a real click, so the final check is to publish with a tiny budget, open your analytics realtime report, click your own live ad, and confirm the session arrives with the right source and medium and a populated utm_content.
Is anything I type here sent anywhere?
No. The builder runs entirely in your browser, nothing is transmitted and nothing is stored. You can use it with a real destination URL without it leaving the page.
Sources
Keep exploring
Turn ad research into winning ads
Research the ads that work, generate the creative on-brand, and launch to Meta, all in one tool.
7-day free trial · No credit card required
