Skip to main content
GUIDE · MICROSOFT ADVERTISING8 min read

Microsoft Advertising offline conversions setup

A practical implementation guide for sending TrackLayer events into Microsoft Advertising as offline conversions, with msclkid capture, goal mapping, backend upload jobs, and correction logic that does not corrupt revenue reporting.

Guide section

Why it matters

Microsoft Advertising is often one of the highest-intent paid channels for B2B and considered-purchase ecommerce because the click frequently begins from explicit search behavior. The problem is that the conversion that matters does not always happen online in the same session. A sales rep may close the order later, a finance system may validate payment after the checkout page, or a CRM workflow may decide whether a lead was actually qualified days after the click.

Offline conversions let TrackLayer bridge that gap. Instead of hoping a browser tag survives long enough to represent the real business outcome, TrackLayer can preserve MicrosoftClickId at the moment of the ad click and later upload the confirmed event from your backend systems. That makes paid search optimization closer to revenue truth and much easier to audit when imported conversions do not match the raw order log.

Guide section

Prerequisites

Microsoft Advertising access with permission to create or inspect offline conversion goals in the correct account and customer hierarchy.

A Developer Token plus OAuth client credentials and refresh token for a user who can upload conversions into the destination Microsoft Advertising account.

Reliable first-party capture of msclkid from paid landing URLs, persisted long enough to survive form submit, checkout, CRM sync, and later offline qualification.

A TrackLayer routing plan that defines which canonical events should become Microsoft offline conversions and which should stay analytics-only.

Operational logging for request IDs, PartialErrors, account IDs, conversion goal names, and the exact source record that generated each upload.

Guide section

Setup

The stable rollout is goal design → msclkid capture → worker auth → controlled upload → adjustment handling. If you skip the early steps, later import debugging becomes mostly guesswork.

Step 01

Create the Microsoft offline conversion goals first

Do not start by uploading payloads. Start by creating the exact conversion goals Microsoft Advertising should receive. The name you upload later must match the goal name exactly, including case and spacing. Keep goal naming stable because your TrackLayer event mapping will depend on it. Most teams should create only a few business-owned goals such as Purchase, Qualified Lead, or Closed Deal rather than mirroring every internal status.

const microsoftGoals = [
  {
    name: "Purchase",
    type: "OfflineConversion",
    revenueMode: "VariableValue",
  },
  {
    name: "Qualified Lead",
    type: "OfflineConversion",
    revenueMode: "NoValue",
  },
];
Step 02

Capture msclkid at the click boundary

The Microsoft click identifier appears on the landing URL and is easy to lose if you wait until checkout or CRM sync to look for it. Capture msclkid on the first eligible request, tie it to the visitor session, and then write it into the lead, cart, or order record TrackLayer will use later. If the person converts through a delayed sales motion, this stored click ID is what lets the offline upload reconnect the backend event to the ad click.

const params = new URLSearchParams(window.location.search);
const msclkid = params.get("msclkid");

if (msclkid) {
  await fetch("/api/tracklayer/ms-attribution", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      msclkid,
      landingUrl: window.location.href,
      sessionId: "sess_10492",
    }),
  });
}
Step 03

Authenticate the upload worker

Offline conversions should be sent by a backend worker with stable account context, not by ad hoc scripts. Use the Microsoft refresh token to obtain a short-lived access token, store account identifiers alongside the token context, and fail the batch if auth is wrong. Partial uploads with the wrong account headers are harder to unwind than a clean failed job.

POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id=MICROSOFT_APP_ID&
client_secret=MICROSOFT_APP_SECRET&
grant_type=refresh_token&
refresh_token=MICROSOFT_REFRESH_TOKEN&
scope=https%3A%2F%2Fads.microsoft.com%2Fmsads.manage%20offline_access
Step 04

Upload offline conversions from TrackLayer

When TrackLayer receives the confirmed business event, build the Microsoft payload from source-of-truth data. Use the original conversion time in UTC, not the worker execution time. Match the goal name exactly, send the stored MicrosoftClickId, and include value and currency for revenue events. Batch by account, but keep one internal dedupe key per source event so retries do not create duplicates.

POST https://campaign.api.bingads.microsoft.com/CampaignManagement/v13/OfflineConversions/Apply
Authorization: Bearer ACCESS_TOKEN
DeveloperToken: DEVELOPER_TOKEN
CustomerAccountId: 123456789
CustomerId: 987654321
Content-Type: application/json

{
  "OfflineConversions": [
    {
      "ConversionName": "Purchase",
      "ConversionTime": "2026-04-24T09:42:13Z",
      "ConversionValue": 129.95,
      "ConversionCurrencyCode": "USD",
      "MicrosoftClickId": "dd4afcccb1c9a4cad9544dd7e5006"
    }
  ]
}
Step 05

Handle corrections with restatements or retractions

Refunds, cancellations, and corrected revenue should update the original imported conversion rather than create a second one. Keep the original goal name, click ID, and conversion time so Microsoft can find the existing record. Then send a restatement when value changed or a retraction when the conversion should no longer count at all.

const adjustment = {
  ConversionName: "Purchase",
  ConversionTime: "2026-04-24T09:42:13Z",
  MicrosoftClickId: "dd4afcccb1c9a4cad9544dd7e5006",
  AdjustmentType: "Restate",
  AdjustmentTime: "2026-04-25T08:05:00Z",
  AdjustmentValue: 99.95,
  AdjustmentCurrencyCode: "USD",
};
Guide section

Event mapping

Treat the mapping table as a production contract. TrackLayer events stay canonical, while Microsoft goal names stay tightly controlled so uploads remain explainable to marketing, sales ops, and finance.

TrackLayer eventMicrosoft goalKey payload fieldsOperational note
purchasePurchaseConversionName, ConversionTime, ConversionValue, MicrosoftClickIdCore ecommerce upload. Use the final backend-confirmed order value.
qualified_leadQualified LeadConversionName, ConversionTime, MicrosoftClickIdBest for CRM-qualified inbound traffic, not raw form volume.
phone_salePurchaseConversionName, ConversionTime, ConversionValue, MicrosoftClickIdUseful when the order closes off-site or after human sales follow-up.
subscription_startSubscription StartConversionName, ConversionTime, ConversionValue, MicrosoftClickIdGood for SaaS or recurring billing flows where checkout is not the only signal.
refundPurchase adjustmentAdjustmentType, AdjustmentTime, original ConversionName, original MicrosoftClickIdDo not upload as a new negative conversion. Use a correction against the original record.
Guide section

Testing

Upload one controlled conversion against a known msclkid

Pick a recent paid click with a preserved MicrosoftClickId, send one test conversion, and record the request metadata from both TrackLayer and Microsoft.

Review PartialErrors and account headers immediately

If Microsoft rejects the record, the response usually points to naming, auth, or timestamp problems. Fix those before testing at higher volume.

Verify the event later in Microsoft Advertising UI

Reporting is delayed, so use API acceptance as the immediate check and the Ads UI as the later confirmation that the goal was attributed and counted as expected.

Guide section

Troubleshooting

AuthenticationFailed

The access token is expired, scoped incorrectly, or tied to a user without account access. Re-check the OAuth user and account headers together.

InvalidConversionName

The uploaded ConversionName does not exactly match the Microsoft offline goal. Compare spelling, spacing, and case before changing anything else.

ConversionTimeTooOld

The uploaded event falls outside the supported lookback or attribution window. Use the original event time, not the later CRM sync time if that time is no longer eligible.

DuplicateMicrosoftClickId combination

You uploaded the same MicrosoftClickId, ConversionName, and ConversionTime pair twice. Add a TrackLayer-side dedupe key for every offline event.

Events accepted but unattributed

The upload reached Microsoft, but the click ID could not be matched to an eligible ad interaction. Audit msclkid capture and retention before questioning bidding.

Guide section

FAQ

Is this the same thing as Microsoft UET Conversions API?

No. This guide is about offline conversions imported through Microsoft Advertising after the business event was confirmed elsewhere. UET CAPI is the server-side path for website events.

How long should TrackLayer keep msclkid?

Long enough to survive the realistic conversion window for your business. Ninety days is a common operational baseline because sales or post-click workflows often outlive the first session.

Can I upload leads without MicrosoftClickId?

For classic offline conversions, MicrosoftClickId is the anchor field. If you lose it, the upload path becomes much weaker or unavailable depending on the workflow.

Should refunds be sent as new negative conversions?

No. Use a restatement or retraction against the original conversion so Microsoft updates the existing record rather than counting a second event.

What should B2B teams optimize toward?

Usually not raw form submits. Most B2B teams get more value by sending qualified lead, opportunity, or closed revenue milestones once sales ops definitions are stable.

Next reads

Related implementation guides

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.