100% Private & Browser Based

Ad Platform URL Macros for UTM Tracking

A macro is a placeholder you write into a click URL that the ad platform replaces with a real value at the moment of the click. It is how a single tracking template can report the campaign, the ad set and the creative for thousands of ads without anybody typing them.

Every platform invented its own syntax, none of them are interchangeable, and all of them break the same way: the moment something percent encodes the placeholder, it stops being a placeholder and becomes literal text in your report.

The syntax by platform

PlatformShapeCommon tokens
Google AdsSingle braces, ValueTrack{campaignid}, {adgroupid}, {creative}, {keyword}, {network}, {device}
Microsoft AdsSingle braces, mixed case{CampaignId}, {AdGroupId}, {AdId}, {keyword}
MetaDouble braces{{campaign.name}}, {{adset.name}}, {{ad.name}}, {{placement}}, {{site_source_name}}
TikTok AdsDouble underscores__CAMPAIGN_NAME__, __AID_NAME__, __CID_NAME__, __PLACEMENT__
Display & Video 360Dollar and braces${CAMPAIGN_ID}, ${LINE_ITEM_ID}, ${CREATIVE_ID}
Campaign Manager 360Percent and exclamation%ecid!, %epid!

Two things are worth noticing in that table. Meta returns names, Google returns numeric IDs. If you want readable campaign names in a report from Google Ads you have to type them, or import cost data and join on utm_id. And Microsoft copied the brace syntax from Google but not the casing, which is why a template pasted from one account into the other silently stops resolving.

Why encoding kills a macro

Most URL builders call a standard encoder on every value before assembling the query string. That is correct behaviour for a campaign name with a space in it. It is fatal for a macro:

{{campaign.name}}   becomes   %7B%7Bcampaign.name%7D%7D
${CREATIVE_ID}      becomes   %24%7BCREATIVE_ID%7D
%ecid!              becomes   %25ecid!

The platform looks for its own token, finds an encoded string that does not match, and passes the URL through untouched. The click still works, and the report fills with rows literally called %7B%7Bcampaign.name%7D%7D.

This is exactly why the UTM builder on this site splits every value into macro and plain segments, encodes only the plain ones, and leaves the macros byte for byte as written. It also skips the capital letters warning inside a macro, because ${CREATIVE_ID} has to stay upper case while a campaign name should not be.

Where the macro goes

Getting the syntax right is only half of it. Each platform has a specific field the macro belongs in, and putting it in the wrong one is the second most common failure.

Google Ads

Prefer the tracking template at account or campaign level, or the final URL suffix if you only need the parameters appended. Putting UTM tags directly in the final URL of every ad works, but it means editing every ad when the convention changes, and it triggers a re review of the ad.

Meta

Use the URL parameters field at ad level. Enter it as utm_source=facebook&utm_medium=paid_social&utm_campaign={{campaign.name}} without a leading question mark. Meta appends it and adds the separator itself.

TikTok

Macros go in the URL itself at ad level. The macro names are ad group and ad rather than ad set and ad, which is why __AID_NAME__ is the ad group and not the ad.

DV360 and Campaign Manager 360

These are click macros expanded by the ad server, not by a bidding platform, so they belong in the click through URL configured on the placement or the creative. If the creative is an HTML5 banner, the URL travels through the clickTag, which is covered in the clickTag generator and can be injected into an existing ZIP with the clickTag editor.

Testing a macro before launch

Macros cannot be tested by loading the URL in a browser, because nothing substitutes them there. What you can do is check three things that catch nearly every failure:

  1. Read the raw URL. The token must appear literally, with no %7B anywhere in it.
  2. Check the platform matches the syntax. Braces for Google and Meta, underscores for TikTok, dollar for DV360. A Meta macro in a Google Ads template does nothing.
  3. Click one live ad the day it launches and look at the landing page URL in the address bar. If the placeholder is still there, the platform did not substitute it, and you have found the problem while it has cost you one click instead of a month.

After launch, a macro that failed shows up unmistakably in analytics as a campaign or content value containing braces. That signature is listed among the causes in why GA4 shows unassigned traffic.

One caution about names

Name macros return whatever the campaign is called in the platform, including spaces, capital letters and punctuation. A campaign called Spring Sale 2026 (UK) FINAL v2 arrives in your report exactly like that, encoded, and it will not group with anything else.

If you use name macros, the naming convention inside the ad platform becomes the naming convention in your analytics, whether you meant it to or not. Either name campaigns the way you want them reported, or use ID macros and join the readable names in later.