Server-side events · Platform reference
Microsoft Advertising Conversions API (CAPI) checker
Microsoft Advertising's Conversions API sends website, CRM, offline and app events from your server to a UET tag, alongside or instead of the UET JavaScript tag. Each event is either a pageLoad or a custom event and must carry at least one identifier, ideally the msclkid captured from the landing URL. Events often show as accepted but don't attribute because eventName doesn't match the conversion goal, msclkid is missing or badly formatted, or a hashed field was silently dropped as a validation warning.
Read from the official documentation on 9 November 2026. Sources are listed at the end.
Check your own setup
msclkid is added to your landing URL by auto-tagging. Paste the curl -sIL output of your tracking link into our redirect chain checker and it shows whether msclkid survives every hop to the final landing page. Without it, CAPI has nothing to attribute to. It doesn't build or validate the CAPI JSON payload, the eventName-to-goal mapping, or your hashing. Our CAPI event checker only reads Meta payloads.
Open the Redirect Chain CheckerEndpoint and authentication
POST https://capi.uet.microsoft.com/v1/{tagId}/events
Authorization: Bearer <ApiToken> header. The token is tied to the UET tag and comes from the UET tag settings (Use Conversions API > Copy Token) or the Campaign Management API call POST /CampaignManagement/v13/UetTagAuthKey/Query
Standard event names
Spelled exactly as Microsoft Advertising expects them. A near miss is treated as a different event.
| Event | Use it for |
|---|---|
| pageLoad | eventType value. Send one per page view or SPA navigation, with eventTime, eventSourceUrl and pageLoadId. Feeds destination-URL goals. Can't carry revenue directly |
| custom | eventType value for user actions. eventName is the event action your custom-event conversion goal matches on. Microsoft defines no fixed list of standard event names |
| purchase | customData.pageType value (retail / dynamic remarketing) |
| cart | customData.pageType value |
| product | customData.pageType value |
| category | customData.pageType value |
| searchresults | customData.pageType value |
| home | customData.pageType value |
| other | customData.pageType value |
Required and recommended fields
| Field | What it needs |
|---|---|
| data | Required array of event objects |
| eventType | Required. Must be "pageLoad" or "custom". Any other value gets a 400 InvalidEnumValue |
| eventTime | Required. UNIX epoch UTC in seconds, within the last 90 days |
| eventId | Required for deduplication. A stable ID, the same as the event_id on the UET tag event |
| eventName | Required for deduplication. The event action for custom conversion goals |
| eventSourceUrl | Required for pageLoad events |
| userData | Required. Must include at least one of anonymousId, externalId, em, ph, msclkid, idfa, gaid |
| customData.value / customData.currency | Variable revenue. currency is a 3-letter ISO 4217 code |
| customData.transactionId | Optional, but recommended for single events such as a purchase. Restate/retract needs it |
| dataProvider | Required for third-party senders |
Match keys and hashing
| Key | Normalise and hash |
|---|---|
| userData.em | Trim whitespace, remove dots from the local part, remove any +alias, lowercase the whole address, then SHA-256 as lowercase hex |
| userData.ph | Normalise to E.164 with country code (e.g. +14255551234), then SHA-256 as lowercase hex |
| userData.anonymousId | Not hashed. Visitor ID (preferably a v1 UUID). Must equal the VID sent in the client-side ID Sync pixel. Never send real user IDs |
| userData.externalId | Anonymised signed-in user ID (ideally a 32-byte hex string). Not a raw ID |
| userData.clientIpAddress | Raw IPv4 or IPv6 |
| userData.clientUserAgent | Raw browser user agent |
| userData.idfa / userData.gaid | Raw mobile advertising IDs |
Click ids
| Click id | Where it comes from |
|---|---|
| msclkid | Appended to the landing URL when auto-tagging is on. Store the latest value (first-party cookie, local storage or server store, suggested retention 90 days), overwrite it on each new click, and send it as userData.msclkid. Must be a valid UUID, sent without hyphens |
Deduplication
- When UET JavaScript and CAPI send the same conversion, use the same UET tagId, the same eventId and a compatible eventName on both. The UET tag passes it as event_id in window.uetq.push('event', ...).
- Keep eventId stable across retries so a retried batch doesn't create duplicate conversions.
- Duplicate conversions reported means eventId is missing or inconsistent between UET and CAPI.
Time limits and batch sizes
- eventTime is UNIX UTC seconds and must be within the last 90 days, or the event gets a 400 InvalidEventTime.
- The 90-day submission limit is separate from the conversion goal's attribution window. The event must also fall inside the goal's window to be attributed.
- Maximum 1,000 events per batch request. Real-time sending is preferred.
- By default one invalid event fails the whole batch (HTTP 400). Set continueOnValidationError: true to skip invalid events. The response then reports eventsReceived.
How to test before you trust it
- API validation response: Read the 400 ValidationError details (index, propertyName, errorCode). Also read HTTP 200 responses for ValidationWarning entries with isWarning: true: those fields were dropped while the event was still accepted
- Conversion goal reporting in Microsoft Advertising: After events are accepted, check that the matching conversion goal records conversions. Accepted events with no conversions point to goal mapping, eventName, timestamp or msclkid problems
Why events arrive but don't attribute
- Events accepted but no conversions: Microsoft's own troubleshooting points to goal configuration, eventName, timestamps and msclkid. The custom event's eventName (plus eventCategory and eventLabel if the goal uses them) must match what the conversion goal expects.
- An invalid em or ph hash doesn't fail the request. The API returns HTTP 200 with an InvalidSha256 warning and drops the field, so match quality falls without any error.
- msclkid must be sent without hyphens. If you don't store it from the landing URL, the server event has no click to attribute to. Visitor ID alone isn't a substitute.
- Double counting happens when UET and CAPI use different eventId values, or when CAPI posts to a different UET tagId than the browser tag.
- adStorageConsent "D" (denied) events aren't used for any advertising purpose, including conversion attribution.
- With the default all-or-nothing batch behaviour, one bad eventTime or eventType makes the API reject all 1,000 events in the request.
- If ID Sync isn't firing client-side, or anonymousId doesn't equal its VID, view-through attribution and audiences suffer. ID Sync is required for remarketing.
- Page load events can't carry revenue. For a destination-URL goal, send a separate custom event with only value and currency and the same pageLoadId.
Sources
Platforms change these rules without notice. If a source says something different from this page, the source wins.