Microsoft Ads is the channel almost everyone neglects. Clicks routinely cost less than the same keywords on Google, yet when I audit accounts, the Bing side is where tracking is in the worst shape. I've opened accounts spending real money with a UET tag firing on every page and zero conversions recorded, because nobody finished the second half of the setup.
| Layer | What sits there |
|---|---|
| Inputs | Page load on every page, purchase dataLayer event, submit_lead_form event, pid push with hashed email |
| One UET tag (bat.js) | One tag ID for the whole site; every conversion goal is defined on top of it |
| Destinations | Event goal: action = purchase, Destination URL goal, Duration and pages-per-visit, Offline import keyed on msclkid |
What is a UET tag and how does Microsoft Ads conversion tracking actually work?
UET is one JavaScript tag (bat.js) that you install once, site-wide, and every conversion goal in your account is defined on top of that single tag. That's the core mental model — different enough from Meta's per-event pixel calls to trip people up. You'll find it under Conversion tracking > UET tag; one numeric tag ID for the whole account.
The goals live separately, under Conversion goals:
- Destination URL — someone lands on a page like /thank-you. Easiest to set up, easiest to break.
- Event — the tag reports a custom event with a matching action, category, label, or value. This is the one you want for purchases and leads.
- Duration and pages-per-visit — engagement goals. Fine for reporting, useless for bidding.
- Offline conversions — uploaded later, keyed on msclkid. More on that below.
Here's the part that burns people: the tag firing and the goal counting are two separate things. UET Tag Helper can show a green tag on every page while your account records nothing. The tag collects. The goal interprets. Both halves have to be right.
- Copy the UET tag ID — In Microsoft Advertising under Conversion tracking, UET tag - the number, not the snippet
- Add the GTM UET template tag — Microsoft Advertising Universal Event Tracking, event type page load, All Pages trigger
- Fire events off your dataLayer — Reuse the same purchase and form-submit pushes that already drive GA4 and Meta
- Pass revenue_value and currency — Then set the goal's revenue to varies by conversion, or every conversion counts as zero
- Match the goal to the event exactly — An action of purchase with an equals condition never matches a goal written Purchase
- Verify in the network tab — Look for the bat.bing.com request, then give a new goal up to 24 hours to report
How do you install the UET tag with Google Tag Manager?
Use GTM's built-in template — Microsoft Advertising Universal Event Tracking — and you're done in five minutes. No custom HTML needed.
- In Microsoft Advertising, copy the tag ID from Conversion tracking > UET tag (just the number, not the snippet).
- In GTM, create a new tag with the Microsoft Advertising UET template and paste the tag ID.
- Event type: page load. Trigger: All Pages, or your consent-gated pageview trigger for EEA traffic.
- Preview, check the network tab for a request to bat.bing.com, publish.
Every event tag you add later references the same tag ID — nothing else to install on the site.
How do you track purchases and leads as UET events?
Fire UET event tags off the exact same dataLayer events that already drive your GA4 and Meta tags — do not build a parallel tracking spine for Microsoft. If your checkout pushes a purchase event with value and currency, that push is your trigger. You built the architecture once. Reuse it.
In GTM: new UET tag, same tag ID, event type set to custom, event action purchase, revenue and currency pulled from your existing dataLayer variables. Under the hood the template is doing this:
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
revenue_value: 149.00,
currency: 'USD'
});
Then in Microsoft Advertising, create an Event goal that matches on action equals purchase and set revenue to "varies by conversion." Same pattern for leads: an action like submit_lead_form fired off your existing form-submit dataLayer event.
Does Microsoft Ads have enhanced conversions?
Yes. Microsoft mirrored Google's approach: you pass a hashed email address or phone number alongside your conversion events, and Microsoft matches conversions back to signed-in users that cookies alone would miss. The label has shifted during rollout, so expect your UI to name it slightly differently depending on the account.
The mechanism is a pid push before your event fires:
window.uetq = window.uetq || [];
window.uetq.push('set', {
pid: {
em: 'user@example.com',
ph: '+15551234567'
}
});
UET hashes the values with SHA-256 before anything leaves the page. If your dataLayer already carries email for Google's enhanced conversions and Meta's advanced matching, wiring the same variable into UET is a ten-minute job.
What is msclkid and why should you capture it yourself?
msclkid is Microsoft's click ID — the equivalent of gclid on Google and fbclid on Meta — appended to your landing page URLs when you enable auto-tagging in your account settings. Turn that on first. UET stores it in a cookie so later conversions can be tied back to the click.
You should also capture msclkid into your own first-party cookie, the way you (hopefully) already capture gclid and fbclid. Same code, one more parameter. Two reasons. Offline conversion imports — closed CRM deals, phone sales — are keyed on msclkid, and if you didn't store it at click time, that revenue is unattributable forever. And Safari's ITP caps JavaScript-set cookies at seven days, so a Bing click that converts on day nine has already lost its thread.
Watch your redirects, too. Anything that strips query parameters — http to https hops, vanity URLs, geo-redirects — silently drops msclkid before your capture code runs. Click one of your own ads and watch the URL bar all the way to rest.
| Imported from Google Ads | Still yours to build |
|---|---|
| Campaigns and ad groups | The UET tag, installed site-wide |
| Keywords and match types | Event tags off your dataLayer |
| Ads and final URLs | Conversion goals with exact matches |
| A fast account launch | msclkid auto-tagging and capture |
Is importing from Google Ads good enough?
The Google Ads import is a good campaign quick-start and a bad tracking strategy. It copies campaigns, ad groups, keywords, and ads. Use it. But your Google conversion tracking does not come with it — Google's tags and conversion actions mean nothing to Microsoft. You still have to install UET, build the event tags, and define the goals, or your imported campaigns run smart bidding with no conversion signal. That's the account state I keep finding in audits: tidy imported campaigns, empty conversion columns.
Why do UET goals break so often?
Almost every broken UET setup fails in one of four ways, and none of them show up as errors anywhere.
- Destination URL goals on single-page checkouts. If your thank-you step swaps in without a real page load — common on Shopify upsell apps and funnel builders — the URL goal never matches. Push a manual pageview (
window.uetq.push('event', 'page_view', { page_path: '/order-complete' })) or, better, use an Event goal fired off your purchase dataLayer event. - Revenue never passed. Conversions count but every one is worth zero, so ROAS bidding has nothing to optimize toward.
- Goal match conditions that don't match. Case mismatches, "equals" where you needed "contains," a label the tag never sends.
- msclkid lost before capture. Redirects stripping parameters, or a consent banner blocking the tag on the landing pageview.
Do you need first-party server-side tracking for Microsoft Ads?
Yes — and Microsoft's smaller conversion volume makes it more urgent, not less, because every lost signal hurts the bidding algorithm more. Plain-language version first: server-side tracking means your site sends its data to a tagging server you control, on your own subdomain, and that server forwards clean events to Microsoft, Google, Meta, and GA4. Instead of five vendor scripts each phoning home from the browser and each getting blocked separately, one first-party stream feeds everything.
For Microsoft Ads specifically, that fixes the leaks this article keeps running into. Ad blockers block requests to bat.bing.com just like they block Meta and Google endpoints; requests to your own subdomain survive. Safari's seven-day cookie cap quietly severs any Bing click older than a week, while a cookie set server-side on your own domain lives long enough to credit the two-week-later conversion. And with one server source of truth instead of a race between browser scripts and consent banners, msclkid gets captured first-party at click time, offline imports join up, and Microsoft, Google, and Meta finally report from the same underlying events. Better data in means Microsoft's bidding stops guessing.
Frequently asked questions
Do I need a separate UET tag for each website?
One UET tag covers one site cleanly. If you run multiple distinct websites, create a separate UET tag for each so goal data and reporting stay separated.
Can I use my Google Ads conversion tracking for Microsoft Ads?
No. Importing campaigns from Google Ads copies the campaigns, not the tracking. Microsoft only counts conversions reported through UET or offline imports.
How long does it take for UET conversions to show up?
Give new goals up to 24 hours. Past a day with real traffic and zero conversions? Check the goal's match conditions against what the tag sends.
Why does UET Tag Helper show my tag working but I get no conversions?
Because the tag and the goals are separate layers. The tag can fire perfectly while the goal matches on the wrong URL or a misspelled event action. Audit the goal definition, not the tag.
How do I track revenue in Microsoft Ads conversions?
Send revenue_value and currency on your UET purchase event, and set the goal's revenue to "varies by conversion." If revenue shows as zero, the event fired without the value attached.
What is msclkid used for?
It's Microsoft's click identifier, appended to landing URLs by auto-tagging. Conversion attribution and offline conversion uploads depend on it, so store it in a first-party cookie at click time alongside gclid and fbclid.
- microsoft ads
- uet
- bing

