> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Bing UET Conversions API

[Server](#)[ Source code](https://github.com/elbwalker/walkerOS/tree/main/packages/server/destinations/bing)[ Package](https://www.npmjs.com/package/@walkeros/server-destination-bing) Beta

Server-side event delivery to Microsoft Advertising's Universal Event Tracking (UET) Conversions API for enhanced conversion tracking in Microsoft Ads campaigns, bypassing browser limitations and improving match quality.

Where this fits

Bing UET CAPI is a **server destination** in the walkerOS flow:

Sends events server-side to Microsoft's UET Conversions API using raw HTTP (no SDK). Identity fields (\`em\`, \`ph\`) are SHA-256 hashed before sending with Microsoft-specific email normalization. Events include a stable \`eventId\` for deduplication with the UET JavaScript tag.

## Installation[​](#installation "Direct link to Installation")

```bash
npm install @walkeros/server-destination-bing
```

* Integrated
* Bundled

```typescript
import { startFlow } from '@walkeros/collector';
import { destinationBing } from '@walkeros/server-destination-bing';

await startFlow({
  destinations: {
    bing: {
      code: destinationBing,
      config: {
        settings: {
          accessToken: 'YOUR_ACCESS_TOKEN',
          tagId: 'YOUR_UET_TAG_ID',
        },
      },
    },
  },
});
```

Add to your `flow.json` destinations:

```json
"destinations": {
  "bing": {
    "package": "@walkeros/server-destination-bing",
    "import": "destinationBing",
    "config": {
      "settings": {
        "accessToken": "YOUR_ACCESS_TOKEN",
        "tagId": "YOUR_UET_TAG_ID"
      }
    }
  }
}
```

[See bundled mode setup](/preview/pr-749/docs/getting-started/modes/bundled.md) | [CLI reference](/preview/pr-749/docs/apps/cli.md)

## Configuration[​](#configuration "Direct link to Configuration")

This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see [destination configuration](/docs/destinations#configuration). Package-specific fields live under `config.settings` and are listed below.

## Settings[​](#settings "Direct link to Settings")

| Property                    | Type                     | Description                                                                                                                                                                                                     | More |
| --------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| `accessToken*`              | `string`                 | Long-lived Bing UET CAPI access token from Microsoft Advertising                                                                                                                                                |      |
| `tagId*`                    | `string`                 | Microsoft Advertising UET tag ID                                                                                                                                                                                |      |
| `url`                       | `string`                 | Custom Bing UET CAPI base URL (default https\://capi.uet.microsoft.com/v1/)                                                                                                                                     |      |
| `doNotHash`                 | `Array<string>`          | User data fields to skip hashing                                                                                                                                                                                |      |
| `user_data`                 | `Record<string, string>` | Mapping for user data fields                                                                                                                                                                                    |      |
| `dataProvider`              | `string`                 | Identifier of the data source (default "walkerOS")                                                                                                                                                              |      |
| `continueOnValidationError` | `boolean`                | When true, Microsoft continues to ingest events despite validation errors                                                                                                                                       |      |
| `ip`                        | `any \| boolean`         | Client IP, sent as userData.clientIpAddress. Resolves against { ingest, event }. Default: \["ingest.ip", "event.user.ip"]. false switches it off. A mapped userData.clientIpAddress wins.                       |      |
| `userAgent`                 | `any \| boolean`         | Client user agent, sent as userData.clientUserAgent. Resolves against { ingest, event }. Default: \["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped userData.clientUserAgent wins. |      |

\* Required fields

## Mapping[​](#mapping "Direct link to Mapping")

Per-event rules under `config.mapping`. For the standard rule fields (consent, condition, data, batch, name, policy) see [mapping](/docs/mapping).

| Property    | Type                     | Description                                                                  | More |
| ----------- | ------------------------ | ---------------------------------------------------------------------------- | ---- |
| `eventType` | `'pageLoad' \| 'custom'` | Override event type: "pageLoad" for page views, "custom" (default) otherwise |      |

## Examples

### Add to cart

A product add is sent to Bing UET as an add\_to\_cart event with value, currency, and item details.

Event

```json
{
  "name": "product add",
  "data": {
    "id": "SKU-B2",
    "name": "Running Shoes",
    "price": 89.99,
    "color": "blue"
  },
  "context": {
    "shopping": [
      "intent",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "SKU-B2",
        "name": "Running Shoes",
        "price": 89.99,
        "quantity": 1
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b1c2d3e4f5a60004",
  "trigger": "click",
  "entity": "product",
  "action": "add",
  "timestamp": 1700000903000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://shop.example.com/products/running-shoes"
  }
}
```

Mapping

```json
{
  "name": "add_to_cart",
  "data": {
    "map": {
      "customData": {
        "map": {
          "value": "data.price",
          "currency": {
            "value": "EUR"
          },
          "items": {
            "loop": [
              "nested",
              {
                "condition": {
                  "$code": "e=>w(e)&&\"product\"===e.entity"
                },
                "map": {
                  "id": "data.id",
                  "name": "data.name",
                  "price": "data.price",
                  "quantity": {
                    "key": "data.quantity",
                    "value": 1
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
}
```

Out

```javascript
sendServer("https://capi.uet.microsoft.com/v1/UET-12345/events", "{\"data\":[{\"eventType\":\"custom\",\"eventId\":\"b1c2d3e4f5a60004\",\"eventTime\":1700000903,\"adStorageConsent\":\"G\",\"userData\":{},\"eventName\":\"add_to_cart\",\"eventSourceUrl\":\"https://shop.example.com/products/running-shoes\",\"customData\":{\"value\":89.99,\"currency\":\"EUR\",\"items\":[{\"id\":\"SKU-B2\",\"name\":\"Running Shoes\",\"price\":89.99,\"quantity\":1}]}}],\"dataProvider\":\"walkerOS\"}", {
  "headers": {
    "Authorization": "Bearer s3cr3t",
    "Content-Type": "application/json"
  }
})
```

### Lead

A newsletter form submission is sent to Bing UET as a lead event with the SHA-256 hashed email.

Event

```json
{
  "name": "form submit",
  "data": {
    "type": "newsletter"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "email": "user@example.com"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b1c2d3e4f5a60003",
  "trigger": "test",
  "entity": "form",
  "action": "submit",
  "timestamp": 1700000902000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://example.com/contact"
  }
}
```

Mapping

```json
{
  "name": "lead",
  "data": {
    "map": {
      "userData": {
        "map": {
          "em": "user.email"
        }
      }
    }
  }
}
```

Out

```javascript
sendServer("https://capi.uet.microsoft.com/v1/UET-12345/events", "{\"data\":[{\"eventType\":\"custom\",\"eventId\":\"b1c2d3e4f5a60003\",\"eventTime\":1700000902,\"adStorageConsent\":\"G\",\"userData\":{\"em\":\"b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514\"},\"eventName\":\"lead\",\"eventSourceUrl\":\"https://example.com/contact\"}],\"dataProvider\":\"walkerOS\"}", {
  "headers": {
    "Authorization": "Bearer s3cr3t",
    "Content-Type": "application/json"
  }
})
```

### Page view

A page view is sent to the Bing UET CAPI with eventType pageLoad and the source URL.

Event

```json
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b1c2d3e4f5a60002",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000901000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://example.com/docs/"
  }
}
```

Mapping

```json
{
  "settings": {
    "eventType": "pageLoad"
  }
}
```

Out

```javascript
sendServer("https://capi.uet.microsoft.com/v1/UET-12345/events", "{\"data\":[{\"eventType\":\"pageLoad\",\"eventId\":\"b1c2d3e4f5a60002\",\"eventTime\":1700000901,\"adStorageConsent\":\"G\",\"userData\":{},\"eventSourceUrl\":\"https://example.com/docs/\"}],\"dataProvider\":\"walkerOS\"}", {
  "headers": {
    "Authorization": "Bearer s3cr3t",
    "Content-Type": "application/json"
  }
})
```

### Purchase

A completed order is sent to the Bing UET CAPI with transaction id, value, items, and hashed user data.

Event

```json
{
  "name": "order complete",
  "data": {
    "id": "ORD-300",
    "total": 249.99,
    "currency": "EUR"
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "user-123",
    "device": "device-456"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "SKU-A1",
        "name": "Widget Pro",
        "price": 124.99,
        "quantity": 2
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b1c2d3e4f5a60001",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000900000,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "browser",
    "platform": "web",
    "url": "https://shop.example.com/checkout/complete"
  }
}
```

Mapping

```json
{
  "name": "purchase",
  "data": {
    "map": {
      "customData": {
        "map": {
          "value": "data.total",
          "currency": {
            "key": "data.currency",
            "value": "EUR"
          },
          "transactionId": "data.id",
          "pageType": {
            "value": "purchase"
          },
          "items": {
            "loop": [
              "nested",
              {
                "condition": {
                  "$code": "e=>w(e)&&\"product\"===e.entity"
                },
                "map": {
                  "id": "data.id",
                  "name": "data.name",
                  "price": "data.price",
                  "quantity": {
                    "key": "data.quantity",
                    "value": 1
                  }
                }
              }
            ]
          }
        }
      },
      "userData": {
        "map": {
          "externalId": "user.id"
        }
      }
    }
  }
}
```

Out

```javascript
sendServer("https://capi.uet.microsoft.com/v1/UET-12345/events", "{\"data\":[{\"eventType\":\"custom\",\"eventId\":\"b1c2d3e4f5a60001\",\"eventTime\":1700000900,\"adStorageConsent\":\"G\",\"userData\":{\"externalId\":\"user-123\"},\"eventName\":\"purchase\",\"eventSourceUrl\":\"https://shop.example.com/checkout/complete\",\"customData\":{\"value\":249.99,\"currency\":\"EUR\",\"transactionId\":\"ORD-300\",\"pageType\":\"purchase\",\"items\":[{\"id\":\"SKU-A1\",\"name\":\"Widget Pro\",\"price\":124.99,\"quantity\":2}]}}],\"dataProvider\":\"walkerOS\"}", {
  "headers": {
    "Authorization": "Bearer s3cr3t",
    "Content-Type": "application/json"
  }
})
```

## Client IP and user agent[​](#client-ip-and-user-agent "Direct link to Client IP and user agent")

The destination sends the client IP as `userData.clientIpAddress` and the user agent as `userData.clientUserAgent` by default. The `ip` and `userAgent` settings resolve against `{ ingest, event }` and default to `["ingest.ip", "event.user.ip"]` and `["ingest.userAgent", "event.user.userAgent"]`, so they fill in whenever the source provides them (see the `config.ingest` recipe on the [Express source](/preview/pr-749/docs/sources/server/express.md#ingest-metadata)). A value your mapping sets for `userData.clientIpAddress` or `userData.clientUserAgent` wins. A value that resolves to nothing is not sent. Set either setting to `false` to turn it off, or to another mapping value to read it elsewhere.

## Event types[​](#event-types "Direct link to Event types")

Bing UET distinguishes two event types. Set the type via `mapping.settings.eventType`:

| `eventType` | When to use                                                 |
| ----------- | ----------------------------------------------------------- |
| `pageLoad`  | Page view events (no `eventName` required)                  |
| `custom`    | All other conversion events (default, requires `eventName`) |

```json
"mapping": {
  "page": {
    "view": {
      "settings": { "eventType": "pageLoad" }
    }
  },
  "order": {
    "complete": {
      "name": "purchase",
      "data": {
        "map": {
          "customData": {
            "map": {
              "value": "data.total",
              "currency": "data.currency",
              "transactionId": "data.id",
              "pageType": { "value": "purchase" }
            }
          }
        }
      }
    }
  }
}
```

### customData structure[​](#customdata-structure "Direct link to customData structure")

Event properties must be nested under `customData`. Common fields include `value`, `currency`, `transactionId`, `items`, `itemIds`, `pageType`, `eventCategory`, `eventLabel`, `eventValue`, `searchTerm`.

## Hashing[​](#hashing "Direct link to Hashing")

Only `em` (email) and `ph` (phone) are SHA-256 hashed before sending. All other identity fields pass through as-is: `anonymousId`, `externalId`, `msclkid`, `clientIpAddress`, `clientUserAgent`, `idfa`, `gaid`.

### Microsoft-specific email normalization[​](#microsoft-specific-email-normalization "Direct link to Microsoft-specific email normalization")

Before hashing, emails are normalized to match Microsoft's canonicalization:

1. Trim whitespace
2. Lowercase the entire address
3. Remove dots from the user portion (`a.b.c@example.com` becomes `abc@example.com`)
4. Strip `+alias` suffix (`user+promo@example.com` becomes `user@example.com`)

Pass raw values and hashing is handled for you. If a value is already hashed or you want to skip hashing for a specific field, use `doNotHash`:

```json
"settings": {
  "accessToken": "YOUR_ACCESS_TOKEN",
  "tagId": "YOUR_UET_TAG_ID",
  "doNotHash": ["em"]
}
```

## Deduplication[​](#deduplication "Direct link to Deduplication")

Each event is sent with `eventId` set to the walkerOS event `id`. If you also run the UET JavaScript tag in the browser, Microsoft deduplicates server and browser events that share the same `eventId` and `eventName`, so conversions are not double-counted.

## Consent[​](#consent "Direct link to Consent")

All events sent to this destination include `adStorageConsent: "G"` (granted). Gate the destination with its `consent` config rather than sending denied events.

## Links[​](#links "Direct link to Links")

* [Microsoft UET Conversions API documentation](https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi)
* [Microsoft Advertising CAPI reference](https://help.ads.microsoft.com/)
