diff --git a/docs/content/scripts/bing-uet.md b/docs/content/scripts/bing-uet.md
index 2b7486007..da016ea10 100644
--- a/docs/content/scripts/bing-uet.md
+++ b/docs/content/scripts/bing-uet.md
@@ -54,3 +54,25 @@ function trackSignup() {
}
```
+
+### Consent Mode
+
+Bing UET supports [advanced consent mode](https://help.ads.microsoft.com/#apex/ads/en/60119/1-500). Use `onBeforeUetStart` to set the default consent state before the script loads. If consent is denied, UET only sends anonymous data.
+
+```vue
+
+```
diff --git a/packages/script/src/registry-types.json b/packages/script/src/registry-types.json
index 01404dc17..e1692b2fc 100644
--- a/packages/script/src/registry-types.json
+++ b/packages/script/src/registry-types.json
@@ -6,10 +6,65 @@
"kind": "const",
"code": "export const BingUetOptions = object({\n /**\n * Your Bing UET tag ID.\n * @see https://help.ads.microsoft.com/#apex/ads/en/56682/2-500\n */\n id: string(),\n /**\n * Enable automatic SPA page tracking.\n * @default true\n */\n enableAutoSpaTracking: optional(boolean()),\n})"
},
+ {
+ "name": "BingUetConsentStatus",
+ "kind": "type",
+ "code": "export type BingUetConsentStatus = 'granted' | 'denied'"
+ },
+ {
+ "name": "BingUetConsentOptions",
+ "kind": "interface",
+ "code": "export interface BingUetConsentOptions {\n /**\n * Controls storage of advertising identifiers. Currently the only field UET honors.\n */\n ad_storage?: BingUetConsentStatus\n}"
+ },
+ {
+ "name": "BingUetEventName",
+ "kind": "type",
+ "code": "export type BingUetEventName\n = | 'page_view'\n | 'screen_view'\n | 'login'\n | 'sign_up'\n | 'subscribe'\n | 'start_trial'\n | 'lead'\n | 'generate_lead'\n | 'submit_lead_form'\n | 'contact'\n | 'search'\n | 'view_search_results'\n | 'select_content'\n | 'share'\n | 'exception'\n | 'find_location'\n | 'book_appointment'\n | 'get_route'\n | 'view_item'\n | 'view_item_list'\n | 'view_promotion'\n | 'add_to_cart'\n | 'remove_from_cart'\n | 'add_to_wishlist'\n | 'add_payment_info'\n | 'begin_checkout'\n | 'checkout_progress'\n | 'set_checkout_option'\n | 'purchase'\n | 'refund'\n | (string & {})"
+ },
+ {
+ "name": "BingUetItem",
+ "kind": "interface",
+ "code": "export interface BingUetItem {\n id?: string\n name?: string\n brand?: string\n category?: string\n variant?: string\n price?: number\n quantity?: number\n list_name?: string\n list_position?: number\n creative_name?: string\n creative_slot?: string\n location_id?: string\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetPromotion",
+ "kind": "interface",
+ "code": "export interface BingUetPromotion {\n id?: string\n name?: string\n creative_name?: string\n creative_slot?: string\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetEventParams",
+ "kind": "interface",
+ "code": "export interface BingUetEventParams {\n /** Event category (beacon shortcut). */\n ec?: string\n /** Event action (beacon shortcut). */\n ea?: string\n /** Event label (beacon shortcut). */\n el?: string\n /** Event value, numeric (beacon shortcut). */\n ev?: number\n /** Goal category / goal completion. */\n gc?: string\n /** Goal value. */\n gv?: number\n /** Long-form alias for `ec`. */\n event_category?: string\n /** Long-form alias for `ea`. */\n event_action?: string\n /** Long-form alias for `el`. */\n event_label?: string\n /** Long-form alias for `ev`. */\n event_value?: number\n /** Unique event identifier (dedup). */\n event_id?: string\n /** Variable revenue amount. */\n revenue_value?: number\n /** ISO 4217 currency code (e.g. \"USD\"). */\n currency?: string\n /** Unique order/transaction ID (dedup). */\n transaction_id?: string\n /** Ecommerce items. */\n items?: BingUetItem[]\n /** Promotions associated with the event. */\n promotions?: BingUetPromotion[]\n /** Sign-up/login method (e.g. \"Google\"). */\n method?: string\n coupon?: string\n tax?: number\n shipping?: number\n affiliation?: string\n /** Search query. */\n search_term?: string\n content_type?: string\n content_id?: string\n checkout_step?: number\n checkout_option?: string\n description?: string\n name?: string\n screen_name?: string\n /** Whether an exception is fatal. */\n fatal?: boolean\n /** Flags a new customer conversion. */\n new_customer?: boolean | number\n /** Retail vertical: product ID. */\n ecomm_prodid?: string | string[]\n /** Retail vertical: page type. */\n ecomm_pagetype?: 'home' | 'searchresults' | 'category' | 'product' | 'cart' | 'purchase' | 'other' | (string & {})\n ecomm_totalvalue?: number\n ecomm_category?: string | string[]\n ecomm_query?: string\n /** Override page path. */\n page_path?: string\n /** Override page title. */\n page_title?: string\n /** Override full page URL. */\n page_location?: string\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetEnhancedConversionsPid",
+ "kind": "interface",
+ "code": "export interface BingUetEnhancedConversionsPid {\n /** SHA-256 hashed email (lowercase, trimmed). Alias: `email`. */\n em?: string\n /** SHA-256 hashed phone (E.164 digits only). Alias: `phone_number`. */\n ph?: string\n /** Long-form alias for `em`. */\n email?: string\n /** Long-form alias for `ph`. */\n phone_number?: string\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetSetParams",
+ "kind": "interface",
+ "code": "export interface BingUetSetParams {\n /** Partner identifiers for enhanced conversions. */\n pid?: BingUetEnhancedConversionsPid\n page_path?: string\n page_title?: string\n page_location?: string\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetTcfConfig",
+ "kind": "interface",
+ "code": "export interface BingUetTcfConfig {\n /** Enable TCF v2.0 auto-consent handling (Microsoft vendorId 1126). */\n enabled?: boolean\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetConstructorOptions",
+ "kind": "interface",
+ "code": "export interface BingUetConstructorOptions {\n /** UET tag ID. */\n ti: string\n /** Alternate tag ID field (same effect as `ti`). */\n tagId?: string\n /** Auto-fire pageLoad on SPA route changes. */\n enableAutoSpaTracking?: boolean\n /** Enable TCF v2.0 auto-consent handling. */\n enableAutoConsent?: boolean\n /** Suppress automatic page_view on load. */\n disableAutoPageView?: boolean\n /** Disable the UET container entirely. */\n disableContainer?: boolean\n /** Disable writing the UET visitor ID cookie. */\n disableUetVid?: boolean\n /** Disable visibility (tab focus/blur) events. */\n disableVisibilityEvents?: boolean\n /** Defer loading the beacon. */\n deferLoad?: boolean\n /** Strip query strings from reported URLs. */\n removeQueryFromUrls?: boolean\n /** Store conversion tracking cookies. */\n storeConvTrackCookies?: boolean\n /** Cookie domain. */\n cookieDomain?: string\n /** Cookie flags (e.g. \"SameSite=None; Secure\"). */\n cookieFlags?: string\n /** Enable MS DNS cookie. */\n msDnsCookie?: boolean\n /** UID cookie name. */\n uidCookie?: string\n /** Error beacon verbosity level. */\n errorBeaconLevel?: number\n /** Microsoft Clarity project ID for integration. */\n clarityProjectId?: string\n /** When true, reads `window.enhanced_conversion_data` for gtag-style enhanced conversions. */\n gtagPid?: boolean\n /** Beacon protocol version. */\n Ver?: 1 | 2\n /** Associated advertiser ID. */\n advertiserId?: string\n /** Source tag for GTM integration. */\n gtmTagSource?: string\n /** Queue reference, typically `window.uetq`. */\n q?: any[]\n [key: string]: any\n}"
+ },
+ {
+ "name": "BingUetQueue",
+ "kind": "interface",
+ "code": "export interface BingUetQueue {\n push: {\n // Legacy custom event object form (beacon shortcuts).\n (event: BingUetEventParams): void\n // Manual page load (maps internally to `page_view`).\n (command: 'pageLoad'): void\n // Standard and custom events.\n (command: 'event', eventName: BingUetEventName, eventParams?: BingUetEventParams): void\n // Consent mode (default on init, update after user interaction).\n (command: 'consent', action: 'default' | 'update', consentParams: BingUetConsentOptions): void\n // Enhanced conversions / sticky page overrides.\n (command: 'set', params: BingUetSetParams): void\n // TCF v2.0 auto-consent configuration.\n (command: 'config', target: 'tcf', params: BingUetTcfConfig): void\n }\n}"
+ },
{
"name": "BingUetApi",
"kind": "interface",
- "code": "export interface BingUetApi {\n uetq: {\n push: (event: string | Record) => void\n }\n}"
+ "code": "export interface BingUetApi {\n uetq: BingUetQueue\n}"
}
],
"bluesky-embed": [
diff --git a/packages/script/src/runtime/registry/bing-uet.ts b/packages/script/src/runtime/registry/bing-uet.ts
index 1f3ac778b..9c4920eb9 100644
--- a/packages/script/src/runtime/registry/bing-uet.ts
+++ b/packages/script/src/runtime/registry/bing-uet.ts
@@ -6,20 +6,245 @@ export { BingUetOptions }
export type BingUetInput = RegistryScriptInput
-export interface BingUetApi {
- uetq: {
- push: (event: string | Record) => void
+export type BingUetConsentStatus = 'granted' | 'denied'
+
+export interface BingUetConsentOptions {
+ /**
+ * Controls storage of advertising identifiers. Currently the only field UET honors.
+ */
+ ad_storage?: BingUetConsentStatus
+}
+
+// Standard event names recognized by UET (from bat.js `knownEvents`), plus string fallback for custom events.
+export type BingUetEventName
+ = | 'page_view'
+ | 'screen_view'
+ | 'login'
+ | 'sign_up'
+ | 'subscribe'
+ | 'start_trial'
+ | 'lead'
+ | 'generate_lead'
+ | 'submit_lead_form'
+ | 'contact'
+ | 'search'
+ | 'view_search_results'
+ | 'select_content'
+ | 'share'
+ | 'exception'
+ | 'find_location'
+ | 'book_appointment'
+ | 'get_route'
+ | 'view_item'
+ | 'view_item_list'
+ | 'view_promotion'
+ | 'add_to_cart'
+ | 'remove_from_cart'
+ | 'add_to_wishlist'
+ | 'add_payment_info'
+ | 'begin_checkout'
+ | 'checkout_progress'
+ | 'set_checkout_option'
+ | 'purchase'
+ | 'refund'
+ | (string & {})
+
+export interface BingUetItem {
+ id?: string
+ name?: string
+ brand?: string
+ category?: string
+ variant?: string
+ price?: number
+ quantity?: number
+ list_name?: string
+ list_position?: number
+ creative_name?: string
+ creative_slot?: string
+ location_id?: string
+ [key: string]: any
+}
+
+export interface BingUetPromotion {
+ id?: string
+ name?: string
+ creative_name?: string
+ creative_slot?: string
+ [key: string]: any
+}
+
+export interface BingUetEventParams {
+ /** Event category (beacon shortcut). */
+ ec?: string
+ /** Event action (beacon shortcut). */
+ ea?: string
+ /** Event label (beacon shortcut). */
+ el?: string
+ /** Event value, numeric (beacon shortcut). */
+ ev?: number
+ /** Goal category / goal completion. */
+ gc?: string
+ /** Goal value. */
+ gv?: number
+ /** Long-form alias for `ec`. */
+ event_category?: string
+ /** Long-form alias for `ea`. */
+ event_action?: string
+ /** Long-form alias for `el`. */
+ event_label?: string
+ /** Long-form alias for `ev`. */
+ event_value?: number
+ /** Unique event identifier (dedup). */
+ event_id?: string
+ /** Variable revenue amount. */
+ revenue_value?: number
+ /** ISO 4217 currency code (e.g. "USD"). */
+ currency?: string
+ /** Unique order/transaction ID (dedup). */
+ transaction_id?: string
+ /** Ecommerce items. */
+ items?: BingUetItem[]
+ /** Promotions associated with the event. */
+ promotions?: BingUetPromotion[]
+ /** Sign-up/login method (e.g. "Google"). */
+ method?: string
+ coupon?: string
+ tax?: number
+ shipping?: number
+ affiliation?: string
+ /** Search query. */
+ search_term?: string
+ content_type?: string
+ content_id?: string
+ checkout_step?: number
+ checkout_option?: string
+ description?: string
+ name?: string
+ screen_name?: string
+ /** Whether an exception is fatal. */
+ fatal?: boolean
+ /** Flags a new customer conversion. */
+ new_customer?: boolean | number
+ /** Retail vertical: product ID. */
+ ecomm_prodid?: string | string[]
+ /** Retail vertical: page type. */
+ ecomm_pagetype?: 'home' | 'searchresults' | 'category' | 'product' | 'cart' | 'purchase' | 'other' | (string & {})
+ ecomm_totalvalue?: number
+ ecomm_category?: string | string[]
+ ecomm_query?: string
+ /** Override page path. */
+ page_path?: string
+ /** Override page title. */
+ page_title?: string
+ /** Override full page URL. */
+ page_location?: string
+ [key: string]: any
+}
+
+export interface BingUetEnhancedConversionsPid {
+ /** SHA-256 hashed email (lowercase, trimmed). Alias: `email`. */
+ em?: string
+ /** SHA-256 hashed phone (E.164 digits only). Alias: `phone_number`. */
+ ph?: string
+ /** Long-form alias for `em`. */
+ email?: string
+ /** Long-form alias for `ph`. */
+ phone_number?: string
+ [key: string]: any
+}
+
+export interface BingUetSetParams {
+ /** Partner identifiers for enhanced conversions. */
+ pid?: BingUetEnhancedConversionsPid
+ page_path?: string
+ page_title?: string
+ page_location?: string
+ [key: string]: any
+}
+
+export interface BingUetTcfConfig {
+ /** Enable TCF v2.0 auto-consent handling (Microsoft vendorId 1126). */
+ enabled?: boolean
+ [key: string]: any
+}
+
+export interface BingUetConstructorOptions {
+ /** UET tag ID. */
+ ti: string
+ /** Alternate tag ID field (same effect as `ti`). */
+ tagId?: string
+ /** Auto-fire pageLoad on SPA route changes. */
+ enableAutoSpaTracking?: boolean
+ /** Enable TCF v2.0 auto-consent handling. */
+ enableAutoConsent?: boolean
+ /** Suppress automatic page_view on load. */
+ disableAutoPageView?: boolean
+ /** Disable the UET container entirely. */
+ disableContainer?: boolean
+ /** Disable writing the UET visitor ID cookie. */
+ disableUetVid?: boolean
+ /** Disable visibility (tab focus/blur) events. */
+ disableVisibilityEvents?: boolean
+ /** Defer loading the beacon. */
+ deferLoad?: boolean
+ /** Strip query strings from reported URLs. */
+ removeQueryFromUrls?: boolean
+ /** Store conversion tracking cookies. */
+ storeConvTrackCookies?: boolean
+ /** Cookie domain. */
+ cookieDomain?: string
+ /** Cookie flags (e.g. "SameSite=None; Secure"). */
+ cookieFlags?: string
+ /** Enable MS DNS cookie. */
+ msDnsCookie?: boolean
+ /** UID cookie name. */
+ uidCookie?: string
+ /** Error beacon verbosity level. */
+ errorBeaconLevel?: number
+ /** Microsoft Clarity project ID for integration. */
+ clarityProjectId?: string
+ /** When true, reads `window.enhanced_conversion_data` for gtag-style enhanced conversions. */
+ gtagPid?: boolean
+ /** Beacon protocol version. */
+ Ver?: 1 | 2
+ /** Associated advertiser ID. */
+ advertiserId?: string
+ /** Source tag for GTM integration. */
+ gtmTagSource?: string
+ /** Queue reference, typically `window.uetq`. */
+ q?: any[]
+ [key: string]: any
+}
+
+export interface BingUetQueue {
+ push: {
+ // Legacy custom event object form (beacon shortcuts).
+ (event: BingUetEventParams): void
+ // Manual page load (maps internally to `page_view`).
+ (command: 'pageLoad'): void
+ // Standard and custom events.
+ (command: 'event', eventName: BingUetEventName, eventParams?: BingUetEventParams): void
+ // Consent mode (default on init, update after user interaction).
+ (command: 'consent', action: 'default' | 'update', consentParams: BingUetConsentOptions): void
+ // Enhanced conversions / sticky page overrides.
+ (command: 'set', params: BingUetSetParams): void
+ // TCF v2.0 auto-consent configuration.
+ (command: 'config', target: 'tcf', params: BingUetTcfConfig): void
}
}
+export interface BingUetApi {
+ uetq: BingUetQueue
+}
+
declare global {
interface Window {
- UET: new (options: { ti: string, enableAutoSpaTracking?: boolean, q?: any[] }) => BingUetApi['uetq']
- uetq: any[] | BingUetApi['uetq']
+ UET: new (options: BingUetConstructorOptions) => BingUetQueue
+ uetq: any[] | BingUetQueue
}
}
-export function useScriptBingUet(_options?: BingUetInput) {
+export function useScriptBingUet(_options?: BingUetInput & { onBeforeUetStart?: (uetq: BingUetQueue) => void }) {
return useRegistryScript('bingUet', options => ({
scriptInput: {
src: 'https://bat.bing.com/bat.js',
@@ -44,7 +269,9 @@ export function useScriptBingUet(_options?: BingUetInput)
clientInit: import.meta.server
? undefined
: () => {
- window.uetq = window.uetq || []
+ const uetq = window.uetq || []
+ window.uetq = uetq
+ _options?.onBeforeUetStart?.(uetq as unknown as BingUetQueue)
},
}), _options)
}
diff --git a/playground/pages/third-parties/bing-uet.vue b/playground/pages/third-parties/bing-uet.vue
index c1707d3df..dab7712e7 100644
--- a/playground/pages/third-parties/bing-uet.vue
+++ b/playground/pages/third-parties/bing-uet.vue
@@ -5,7 +5,14 @@ useHead({
title: 'Bing UET',
})
-const { status, proxy } = useScriptBingUet({ id: '247021147' })
+const { status, proxy } = useScriptBingUet({
+ id: '247021147',
+ onBeforeUetStart(uetq) {
+ uetq.push('consent', 'default', {
+ ad_storage: 'denied',
+ })
+ },
+})
function triggerEvent() {
proxy.uetq.push('event', 'purchase', {
@@ -13,6 +20,12 @@ function triggerEvent() {
currency: 'USD',
})
}
+
+function grantConsent() {
+ proxy.uetq.push('consent', 'update', {
+ ad_storage: 'granted',
+ })
+}
@@ -24,6 +37,9 @@ function triggerEvent() {
+