@walkeros/server-destination-bing 3.4.0-next-1776749829492

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,132 @@
1
+ import { Mapping as Mapping$1, Destination as Destination$1 } from '@walkeros/core';
2
+ import { DestinationServer, sendServer } from '@walkeros/server-core';
3
+
4
+ interface Settings {
5
+ accessToken: string;
6
+ tagId: string;
7
+ url?: string;
8
+ doNotHash?: string[];
9
+ user_data?: Mapping$1.Map;
10
+ dataProvider?: string;
11
+ continueOnValidationError?: boolean;
12
+ }
13
+ type InitSettings = Partial<Settings>;
14
+ interface Mapping {
15
+ eventType?: EventType;
16
+ }
17
+ interface Env extends DestinationServer.Env {
18
+ sendServer?: typeof sendServer;
19
+ }
20
+ type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
21
+ interface Destination extends DestinationServer.Destination<Types> {
22
+ init: DestinationServer.InitFn<Types>;
23
+ }
24
+ type Config = {
25
+ settings: Settings;
26
+ } & DestinationServer.Config<Types>;
27
+ type InitFn = DestinationServer.InitFn<Types>;
28
+ type PushFn = DestinationServer.PushFn<Types>;
29
+ type PartialConfig = DestinationServer.PartialConfig<Types>;
30
+ type PushEvents = DestinationServer.PushEvents<Mapping>;
31
+ type Rule = Mapping$1.Rule<Mapping>;
32
+ type Rules = Mapping$1.Rules<Rule>;
33
+ /**
34
+ * Microsoft Advertising (Bing) UET Conversions API
35
+ * https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi
36
+ */
37
+ type EventType = 'pageLoad' | 'custom';
38
+ type AdStorageConsent = 'G' | 'D';
39
+ interface CAPIRequestBody {
40
+ data: CAPIEvent[];
41
+ dataProvider?: string;
42
+ continueOnValidationError?: boolean;
43
+ }
44
+ interface CAPIEvent {
45
+ eventType: EventType;
46
+ eventId?: string;
47
+ eventName?: string;
48
+ eventTime: number;
49
+ eventSourceUrl?: string;
50
+ pageLoadId?: string;
51
+ referrerUrl?: string;
52
+ pageTitle?: string;
53
+ keywords?: string;
54
+ adStorageConsent?: AdStorageConsent;
55
+ userData?: UserData;
56
+ customData?: CustomData;
57
+ }
58
+ interface UserData {
59
+ /** Anonymous ID. Do NOT hash. */
60
+ anonymousId?: string;
61
+ /** External/customer ID. Do NOT hash. */
62
+ externalId?: string;
63
+ /** Email, SHA-256 hashed, normalized (dots/alias stripped, lowercased) */
64
+ em?: string;
65
+ /** Phone number, SHA-256 hashed, trimmed */
66
+ ph?: string;
67
+ /** Microsoft click ID. Do NOT hash. */
68
+ msclkid?: string;
69
+ /** Client IP address (IPv4 or IPv6). Do NOT hash. */
70
+ clientIpAddress?: string;
71
+ /** Client user agent. Do NOT hash. */
72
+ clientUserAgent?: string;
73
+ /** iOS IDFA. Do NOT hash. */
74
+ idfa?: string;
75
+ /** Android advertising ID (GAID). Do NOT hash. */
76
+ gaid?: string;
77
+ }
78
+ interface CustomData {
79
+ eventCategory?: string;
80
+ eventLabel?: string;
81
+ eventValue?: number;
82
+ searchTerm?: string;
83
+ transactionId?: string;
84
+ value?: number;
85
+ currency?: string;
86
+ items?: ItemData[];
87
+ itemIds?: string[];
88
+ pageType?: string;
89
+ ecommTotalValue?: number;
90
+ ecommCategory?: string;
91
+ hotelData?: Record<string, unknown>;
92
+ [key: string]: unknown;
93
+ }
94
+ interface ItemData {
95
+ id?: string;
96
+ quantity?: number;
97
+ price?: number;
98
+ name?: string;
99
+ }
100
+ interface ResponseBody {
101
+ status?: string;
102
+ requestId?: string;
103
+ }
104
+
105
+ type index_AdStorageConsent = AdStorageConsent;
106
+ type index_CAPIEvent = CAPIEvent;
107
+ type index_CAPIRequestBody = CAPIRequestBody;
108
+ type index_Config = Config;
109
+ type index_CustomData = CustomData;
110
+ type index_Destination = Destination;
111
+ type index_Env = Env;
112
+ type index_EventType = EventType;
113
+ type index_InitFn = InitFn;
114
+ type index_InitSettings = InitSettings;
115
+ type index_ItemData = ItemData;
116
+ type index_Mapping = Mapping;
117
+ type index_PartialConfig = PartialConfig;
118
+ type index_PushEvents = PushEvents;
119
+ type index_PushFn = PushFn;
120
+ type index_ResponseBody = ResponseBody;
121
+ type index_Rule = Rule;
122
+ type index_Rules = Rules;
123
+ type index_Settings = Settings;
124
+ type index_Types = Types;
125
+ type index_UserData = UserData;
126
+ declare namespace index {
127
+ export type { index_AdStorageConsent as AdStorageConsent, index_CAPIEvent as CAPIEvent, index_CAPIRequestBody as CAPIRequestBody, index_Config as Config, index_CustomData as CustomData, index_Destination as Destination, index_Env as Env, index_EventType as EventType, index_InitFn as InitFn, index_InitSettings as InitSettings, index_ItemData as ItemData, index_Mapping as Mapping, index_PartialConfig as PartialConfig, index_PushEvents as PushEvents, index_PushFn as PushFn, index_ResponseBody as ResponseBody, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types, index_UserData as UserData };
128
+ }
129
+
130
+ declare const destinationBing: Destination;
131
+
132
+ export { index as DestinationBing, destinationBing as default, destinationBing };
@@ -0,0 +1,132 @@
1
+ import { Mapping as Mapping$1, Destination as Destination$1 } from '@walkeros/core';
2
+ import { DestinationServer, sendServer } from '@walkeros/server-core';
3
+
4
+ interface Settings {
5
+ accessToken: string;
6
+ tagId: string;
7
+ url?: string;
8
+ doNotHash?: string[];
9
+ user_data?: Mapping$1.Map;
10
+ dataProvider?: string;
11
+ continueOnValidationError?: boolean;
12
+ }
13
+ type InitSettings = Partial<Settings>;
14
+ interface Mapping {
15
+ eventType?: EventType;
16
+ }
17
+ interface Env extends DestinationServer.Env {
18
+ sendServer?: typeof sendServer;
19
+ }
20
+ type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
21
+ interface Destination extends DestinationServer.Destination<Types> {
22
+ init: DestinationServer.InitFn<Types>;
23
+ }
24
+ type Config = {
25
+ settings: Settings;
26
+ } & DestinationServer.Config<Types>;
27
+ type InitFn = DestinationServer.InitFn<Types>;
28
+ type PushFn = DestinationServer.PushFn<Types>;
29
+ type PartialConfig = DestinationServer.PartialConfig<Types>;
30
+ type PushEvents = DestinationServer.PushEvents<Mapping>;
31
+ type Rule = Mapping$1.Rule<Mapping>;
32
+ type Rules = Mapping$1.Rules<Rule>;
33
+ /**
34
+ * Microsoft Advertising (Bing) UET Conversions API
35
+ * https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi
36
+ */
37
+ type EventType = 'pageLoad' | 'custom';
38
+ type AdStorageConsent = 'G' | 'D';
39
+ interface CAPIRequestBody {
40
+ data: CAPIEvent[];
41
+ dataProvider?: string;
42
+ continueOnValidationError?: boolean;
43
+ }
44
+ interface CAPIEvent {
45
+ eventType: EventType;
46
+ eventId?: string;
47
+ eventName?: string;
48
+ eventTime: number;
49
+ eventSourceUrl?: string;
50
+ pageLoadId?: string;
51
+ referrerUrl?: string;
52
+ pageTitle?: string;
53
+ keywords?: string;
54
+ adStorageConsent?: AdStorageConsent;
55
+ userData?: UserData;
56
+ customData?: CustomData;
57
+ }
58
+ interface UserData {
59
+ /** Anonymous ID. Do NOT hash. */
60
+ anonymousId?: string;
61
+ /** External/customer ID. Do NOT hash. */
62
+ externalId?: string;
63
+ /** Email, SHA-256 hashed, normalized (dots/alias stripped, lowercased) */
64
+ em?: string;
65
+ /** Phone number, SHA-256 hashed, trimmed */
66
+ ph?: string;
67
+ /** Microsoft click ID. Do NOT hash. */
68
+ msclkid?: string;
69
+ /** Client IP address (IPv4 or IPv6). Do NOT hash. */
70
+ clientIpAddress?: string;
71
+ /** Client user agent. Do NOT hash. */
72
+ clientUserAgent?: string;
73
+ /** iOS IDFA. Do NOT hash. */
74
+ idfa?: string;
75
+ /** Android advertising ID (GAID). Do NOT hash. */
76
+ gaid?: string;
77
+ }
78
+ interface CustomData {
79
+ eventCategory?: string;
80
+ eventLabel?: string;
81
+ eventValue?: number;
82
+ searchTerm?: string;
83
+ transactionId?: string;
84
+ value?: number;
85
+ currency?: string;
86
+ items?: ItemData[];
87
+ itemIds?: string[];
88
+ pageType?: string;
89
+ ecommTotalValue?: number;
90
+ ecommCategory?: string;
91
+ hotelData?: Record<string, unknown>;
92
+ [key: string]: unknown;
93
+ }
94
+ interface ItemData {
95
+ id?: string;
96
+ quantity?: number;
97
+ price?: number;
98
+ name?: string;
99
+ }
100
+ interface ResponseBody {
101
+ status?: string;
102
+ requestId?: string;
103
+ }
104
+
105
+ type index_AdStorageConsent = AdStorageConsent;
106
+ type index_CAPIEvent = CAPIEvent;
107
+ type index_CAPIRequestBody = CAPIRequestBody;
108
+ type index_Config = Config;
109
+ type index_CustomData = CustomData;
110
+ type index_Destination = Destination;
111
+ type index_Env = Env;
112
+ type index_EventType = EventType;
113
+ type index_InitFn = InitFn;
114
+ type index_InitSettings = InitSettings;
115
+ type index_ItemData = ItemData;
116
+ type index_Mapping = Mapping;
117
+ type index_PartialConfig = PartialConfig;
118
+ type index_PushEvents = PushEvents;
119
+ type index_PushFn = PushFn;
120
+ type index_ResponseBody = ResponseBody;
121
+ type index_Rule = Rule;
122
+ type index_Rules = Rules;
123
+ type index_Settings = Settings;
124
+ type index_Types = Types;
125
+ type index_UserData = UserData;
126
+ declare namespace index {
127
+ export type { index_AdStorageConsent as AdStorageConsent, index_CAPIEvent as CAPIEvent, index_CAPIRequestBody as CAPIRequestBody, index_Config as Config, index_CustomData as CustomData, index_Destination as Destination, index_Env as Env, index_EventType as EventType, index_InitFn as InitFn, index_InitSettings as InitSettings, index_ItemData as ItemData, index_Mapping as Mapping, index_PartialConfig as PartialConfig, index_PushEvents as PushEvents, index_PushFn as PushFn, index_ResponseBody as ResponseBody, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types, index_UserData as UserData };
128
+ }
129
+
130
+ declare const destinationBing: Destination;
131
+
132
+ export { index as DestinationBing, destinationBing as default, destinationBing };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationBing:()=>types_exports,default:()=>index_default,destinationBing:()=>destinationBing}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var import_core=require("@walkeros/core"),import_server_core2=require("@walkeros/server-core"),import_server_core=require("@walkeros/server-core"),keysToHash=["em","ph"];async function hashUserData(userData,doNotHash=[]){const entries=await Promise.all(Object.entries(userData).map(async([key,value])=>{if(void 0===value)return[key,value];if(function(key,doNotHash=[]){return keysToHash.includes(key)&&!doNotHash.includes(key)}(key,doNotHash)){const normalized=function(key,value){return"em"===key?function(value){const trimmed=value.trim().toLowerCase(),atIndex=trimmed.lastIndexOf("@");if(atIndex<0)return trimmed;const user=trimmed.slice(0,atIndex),domain=trimmed.slice(atIndex+1),aliasIndex=user.indexOf("+");return`${(aliasIndex<0?user:user.slice(0,aliasIndex)).replace(/\./g,"")}@${domain}`}(value):"ph"===key?function(value){return value.trim()}(value):value}(key,String(value));return[key,await(0,import_server_core.getHashServer)(normalized)]}return[key,value]}));return Object.fromEntries(entries)}var types_exports={},destinationBing={type:"bing",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{accessToken:accessToken,tagId:tagId}=settings;accessToken||logger.throw("Config settings accessToken missing"),tagId||logger.throw("Config settings tagId missing");const settingsConfig={url:"https://capi.uet.microsoft.com/v1/",dataProvider:"walkerOS",...settings,accessToken:accessToken,tagId:tagId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,env:env,logger:logger}){var _a;const{accessToken:accessToken,tagId:tagId,url:url="https://capi.uet.microsoft.com/v1/",doNotHash:doNotHash,user_data:user_data,dataProvider:dataProvider="walkerOS",continueOnValidationError:continueOnValidationError}=config.settings,eventData=(0,import_core.isObject)(data)?data:{},configData=config.data?await(0,import_core.getMappingValue)(event,config.data):{},userDataCustom=user_data?await(0,import_core.getMappingValue)(event,{map:user_data}):{},ruleSettings=null==rule?void 0:rule.settings,eventType="pageLoad"===(null==ruleSettings?void 0:ruleSettings.eventType)?"pageLoad":"custom",eventMappedUserData=(0,import_core.isObject)(eventData.userData)?eventData.userData:{},userData={...(0,import_core.isObject)(configData)&&(0,import_core.isObject)(configData.userData)?configData.userData:{},...(0,import_core.isObject)(userDataCustom)?userDataCustom:{},...eventMappedUserData},hashedUserData=await hashUserData(userData,doNotHash),customData={};(0,import_core.isObject)(eventData.customData)&&Object.assign(customData,eventData.customData);for(const[key,value]of Object.entries(eventData))"userData"!==key&&"customData"!==key&&(customData[key]=value);const capiEvent={eventType:eventType,eventId:event.id,eventTime:Math.round((event.timestamp||Date.now())/1e3),adStorageConsent:"G",userData:hashedUserData};"custom"===eventType&&(capiEvent.eventName=(null==rule?void 0:rule.name)||event.name),(null==(_a=event.source)?void 0:_a.id)&&(capiEvent.eventSourceUrl=event.source.id),Object.keys(customData).length>0&&(capiEvent.customData=customData);const body={data:[capiEvent],dataProvider:dataProvider};void 0!==continueOnValidationError&&(body.continueOnValidationError=continueOnValidationError);const endpoint=`${url}${tagId}/events`;logger.debug("Calling Bing UET CAPI",{endpoint:endpoint,method:"POST",eventType:capiEvent.eventType,eventName:capiEvent.eventName,eventId:capiEvent.eventId});const sendServerFn=(null==env?void 0:env.sendServer)||import_server_core2.sendServer,result=await sendServerFn(endpoint,JSON.stringify(body),{headers:{Authorization:`Bearer ${accessToken}`,"Content-Type":"application/json"}});logger.debug("Bing UET CAPI response",{ok:!(0,import_core.isObject)(result)||result.ok}),(0,import_core.isObject)(result)&&!1===result.ok&&logger.throw(`Bing UET CAPI error: ${JSON.stringify(result)}`)}(event,context)},index_default=destinationBing;//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/hash.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationBing from './types';\n\nexport const destinationBing: Destination = {\n type: 'bing',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationBing;\n","import type { Config, Settings, PartialConfig } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { accessToken, tagId } = settings;\n\n if (!accessToken) logger.throw('Config settings accessToken missing');\n if (!tagId) logger.throw('Config settings tagId missing');\n\n const settingsConfig: Settings = {\n url: 'https://capi.uet.microsoft.com/v1/',\n dataProvider: 'walkerOS',\n ...settings,\n accessToken,\n tagId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CAPIEvent,\n CAPIRequestBody,\n CustomData,\n Env,\n EventType,\n PushFn,\n Settings,\n UserData,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashUserData } from './hash';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger },\n) {\n const {\n accessToken,\n tagId,\n url = 'https://capi.uet.microsoft.com/v1/',\n doNotHash,\n user_data,\n dataProvider = 'walkerOS',\n continueOnValidationError,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data)\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data })\n : {};\n\n // Resolve mapping-level eventType override (rule.settings.eventType)\n const ruleSettings = rule?.settings as { eventType?: EventType } | undefined;\n const eventType: EventType =\n ruleSettings?.eventType === 'pageLoad' ? 'pageLoad' : 'custom';\n\n // Build user_data from merge sources (priority: later overrides earlier)\n const eventMappedUserData = isObject(eventData.userData)\n ? (eventData.userData as UserData)\n : {};\n\n const userData: UserData = {\n ...(isObject(configData) && isObject(configData.userData)\n ? (configData.userData as UserData)\n : {}),\n ...(isObject(userDataCustom) ? (userDataCustom as UserData) : {}),\n ...eventMappedUserData,\n };\n\n // Hash identity fields (em, ph only; with Microsoft email normalization)\n const hashedUserData = await hashUserData(userData, doNotHash);\n\n // Build customData from mapped event data\n const customData: CustomData = {};\n if (isObject(eventData.customData)) {\n Object.assign(customData, eventData.customData);\n }\n for (const [key, value] of Object.entries(eventData)) {\n if (key === 'userData' || key === 'customData') continue;\n customData[key] = value;\n }\n\n // Build Bing CAPI event\n const capiEvent: CAPIEvent = {\n eventType,\n eventId: event.id,\n eventTime: Math.round((event.timestamp || Date.now()) / 1000),\n adStorageConsent: 'G',\n userData: hashedUserData,\n };\n\n if (eventType === 'custom') {\n capiEvent.eventName = rule?.name || event.name;\n }\n\n if (event.source?.id) {\n capiEvent.eventSourceUrl = event.source.id;\n }\n\n if (Object.keys(customData).length > 0) {\n capiEvent.customData = customData;\n }\n\n const body: CAPIRequestBody = {\n data: [capiEvent],\n dataProvider,\n };\n\n if (continueOnValidationError !== undefined) {\n body.continueOnValidationError = continueOnValidationError;\n }\n\n const endpoint = `${url}${tagId}/events`;\n\n logger.debug('Calling Bing UET CAPI', {\n endpoint,\n method: 'POST',\n eventType: capiEvent.eventType,\n eventName: capiEvent.eventName,\n eventId: capiEvent.eventId,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n });\n\n logger.debug('Bing UET CAPI response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Bing UET CAPI error: ${JSON.stringify(result)}`);\n }\n};\n","import type { UserData } from './types';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Bing UET CAPI user data fields that must be SHA-256 hashed before sending.\n * Only `em` and `ph` are hashable; all other identity fields pass through\n * unhashed (anonymousId, externalId, msclkid, clientIpAddress,\n * clientUserAgent, idfa, gaid).\n * https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi\n */\nconst keysToHash = ['em', 'ph'];\n\n/**\n * Microsoft-specific email normalization:\n * - Trim whitespace\n * - Lowercase\n * - Split at `@`\n * - Remove dots from the user portion\n * - Strip `+alias` suffix from the user portion\n * - Rejoin\n */\nexport function normalizeEmail(value: string): string {\n const trimmed = value.trim().toLowerCase();\n const atIndex = trimmed.lastIndexOf('@');\n if (atIndex < 0) return trimmed;\n\n const user = trimmed.slice(0, atIndex);\n const domain = trimmed.slice(atIndex + 1);\n\n const aliasIndex = user.indexOf('+');\n const beforeAlias = aliasIndex < 0 ? user : user.slice(0, aliasIndex);\n const normalizedUser = beforeAlias.replace(/\\./g, '');\n\n return `${normalizedUser}@${domain}`;\n}\n\nfunction normalizePhone(value: string): string {\n return value.trim();\n}\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\n}\n\nfunction normalizeForKey(key: string, value: string): string {\n if (key === 'em') return normalizeEmail(value);\n if (key === 'ph') return normalizePhone(value);\n return value;\n}\n\nexport async function hashUserData(\n userData: UserData,\n doNotHash: string[] = [],\n): Promise<UserData> {\n const entries = await Promise.all(\n Object.entries(userData).map(async ([key, value]) => {\n if (value === undefined) return [key, value];\n if (shouldBeHashed(key, doNotHash)) {\n const normalized = normalizeForKey(key, String(value));\n return [key, await getHashServer(normalized)];\n }\n return [key, value];\n }),\n );\n\n return Object.fromEntries(entries) as UserData;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\nexport interface Settings {\n accessToken: string;\n tagId: string;\n url?: string;\n doNotHash?: string[];\n user_data?: WalkerOSMapping.Map;\n dataProvider?: string;\n continueOnValidationError?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n eventType?: EventType;\n}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/**\n * Microsoft Advertising (Bing) UET Conversions API\n * https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi\n */\nexport type EventType = 'pageLoad' | 'custom';\n\nexport type AdStorageConsent = 'G' | 'D';\n\nexport interface CAPIRequestBody {\n data: CAPIEvent[];\n dataProvider?: string;\n continueOnValidationError?: boolean;\n}\n\nexport interface CAPIEvent {\n eventType: EventType;\n eventId?: string;\n eventName?: string;\n eventTime: number;\n eventSourceUrl?: string;\n pageLoadId?: string;\n referrerUrl?: string;\n pageTitle?: string;\n keywords?: string;\n adStorageConsent?: AdStorageConsent;\n userData?: UserData;\n customData?: CustomData;\n}\n\n// User identity fields. Hashable: em, ph. Non-hashable: anonymousId,\n// externalId, msclkid, clientIpAddress, clientUserAgent, idfa, gaid.\nexport interface UserData {\n /** Anonymous ID. Do NOT hash. */\n anonymousId?: string;\n /** External/customer ID. Do NOT hash. */\n externalId?: string;\n /** Email, SHA-256 hashed, normalized (dots/alias stripped, lowercased) */\n em?: string;\n /** Phone number, SHA-256 hashed, trimmed */\n ph?: string;\n /** Microsoft click ID. Do NOT hash. */\n msclkid?: string;\n /** Client IP address (IPv4 or IPv6). Do NOT hash. */\n clientIpAddress?: string;\n /** Client user agent. Do NOT hash. */\n clientUserAgent?: string;\n /** iOS IDFA. Do NOT hash. */\n idfa?: string;\n /** Android advertising ID (GAID). Do NOT hash. */\n gaid?: string;\n}\n\nexport interface CustomData {\n eventCategory?: string;\n eventLabel?: string;\n eventValue?: number;\n searchTerm?: string;\n transactionId?: string;\n value?: number;\n currency?: string;\n items?: ItemData[];\n itemIds?: string[];\n pageType?: string;\n ecommTotalValue?: number;\n ecommCategory?: string;\n hotelData?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface ItemData {\n id?: string;\n quantity?: number;\n price?: number;\n name?: string;\n}\n\nexport interface ResponseBody {\n status?: string;\n requestId?: string;\n}\n"],"mappings":"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","names":["import_server_core"]}
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{getMappingValue,isObject}from"@walkeros/core";import{sendServer}from"@walkeros/server-core";import{getHashServer}from"@walkeros/server-core";var keysToHash=["em","ph"];async function hashUserData(userData,doNotHash=[]){const entries=await Promise.all(Object.entries(userData).map(async([key,value])=>{if(void 0===value)return[key,value];if(function(key,doNotHash=[]){return keysToHash.includes(key)&&!doNotHash.includes(key)}(key,doNotHash)){const normalized=function(key,value){return"em"===key?function(value){const trimmed=value.trim().toLowerCase(),atIndex=trimmed.lastIndexOf("@");if(atIndex<0)return trimmed;const user=trimmed.slice(0,atIndex),domain=trimmed.slice(atIndex+1),aliasIndex=user.indexOf("+");return`${(aliasIndex<0?user:user.slice(0,aliasIndex)).replace(/\./g,"")}@${domain}`}(value):"ph"===key?function(value){return value.trim()}(value):value}(key,String(value));return[key,await getHashServer(normalized)]}return[key,value]}));return Object.fromEntries(entries)}var types_exports={},destinationBing={type:"bing",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{accessToken:accessToken,tagId:tagId}=settings;accessToken||logger.throw("Config settings accessToken missing"),tagId||logger.throw("Config settings tagId missing");const settingsConfig={url:"https://capi.uet.microsoft.com/v1/",dataProvider:"walkerOS",...settings,accessToken:accessToken,tagId:tagId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,env:env,logger:logger}){var _a;const{accessToken:accessToken,tagId:tagId,url:url="https://capi.uet.microsoft.com/v1/",doNotHash:doNotHash,user_data:user_data,dataProvider:dataProvider="walkerOS",continueOnValidationError:continueOnValidationError}=config.settings,eventData=isObject(data)?data:{},configData=config.data?await getMappingValue(event,config.data):{},userDataCustom=user_data?await getMappingValue(event,{map:user_data}):{},ruleSettings=null==rule?void 0:rule.settings,eventType="pageLoad"===(null==ruleSettings?void 0:ruleSettings.eventType)?"pageLoad":"custom",eventMappedUserData=isObject(eventData.userData)?eventData.userData:{},userData={...isObject(configData)&&isObject(configData.userData)?configData.userData:{},...isObject(userDataCustom)?userDataCustom:{},...eventMappedUserData},hashedUserData=await hashUserData(userData,doNotHash),customData={};isObject(eventData.customData)&&Object.assign(customData,eventData.customData);for(const[key,value]of Object.entries(eventData))"userData"!==key&&"customData"!==key&&(customData[key]=value);const capiEvent={eventType:eventType,eventId:event.id,eventTime:Math.round((event.timestamp||Date.now())/1e3),adStorageConsent:"G",userData:hashedUserData};"custom"===eventType&&(capiEvent.eventName=(null==rule?void 0:rule.name)||event.name),(null==(_a=event.source)?void 0:_a.id)&&(capiEvent.eventSourceUrl=event.source.id),Object.keys(customData).length>0&&(capiEvent.customData=customData);const body={data:[capiEvent],dataProvider:dataProvider};void 0!==continueOnValidationError&&(body.continueOnValidationError=continueOnValidationError);const endpoint=`${url}${tagId}/events`;logger.debug("Calling Bing UET CAPI",{endpoint:endpoint,method:"POST",eventType:capiEvent.eventType,eventName:capiEvent.eventName,eventId:capiEvent.eventId});const sendServerFn=(null==env?void 0:env.sendServer)||sendServer,result=await sendServerFn(endpoint,JSON.stringify(body),{headers:{Authorization:`Bearer ${accessToken}`,"Content-Type":"application/json"}});logger.debug("Bing UET CAPI response",{ok:!isObject(result)||result.ok}),isObject(result)&&!1===result.ok&&logger.throw(`Bing UET CAPI error: ${JSON.stringify(result)}`)}(event,context)},index_default=destinationBing;export{types_exports as DestinationBing,index_default as default,destinationBing};//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/hash.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { accessToken, tagId } = settings;\n\n if (!accessToken) logger.throw('Config settings accessToken missing');\n if (!tagId) logger.throw('Config settings tagId missing');\n\n const settingsConfig: Settings = {\n url: 'https://capi.uet.microsoft.com/v1/',\n dataProvider: 'walkerOS',\n ...settings,\n accessToken,\n tagId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CAPIEvent,\n CAPIRequestBody,\n CustomData,\n Env,\n EventType,\n PushFn,\n Settings,\n UserData,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashUserData } from './hash';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger },\n) {\n const {\n accessToken,\n tagId,\n url = 'https://capi.uet.microsoft.com/v1/',\n doNotHash,\n user_data,\n dataProvider = 'walkerOS',\n continueOnValidationError,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data)\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data })\n : {};\n\n // Resolve mapping-level eventType override (rule.settings.eventType)\n const ruleSettings = rule?.settings as { eventType?: EventType } | undefined;\n const eventType: EventType =\n ruleSettings?.eventType === 'pageLoad' ? 'pageLoad' : 'custom';\n\n // Build user_data from merge sources (priority: later overrides earlier)\n const eventMappedUserData = isObject(eventData.userData)\n ? (eventData.userData as UserData)\n : {};\n\n const userData: UserData = {\n ...(isObject(configData) && isObject(configData.userData)\n ? (configData.userData as UserData)\n : {}),\n ...(isObject(userDataCustom) ? (userDataCustom as UserData) : {}),\n ...eventMappedUserData,\n };\n\n // Hash identity fields (em, ph only; with Microsoft email normalization)\n const hashedUserData = await hashUserData(userData, doNotHash);\n\n // Build customData from mapped event data\n const customData: CustomData = {};\n if (isObject(eventData.customData)) {\n Object.assign(customData, eventData.customData);\n }\n for (const [key, value] of Object.entries(eventData)) {\n if (key === 'userData' || key === 'customData') continue;\n customData[key] = value;\n }\n\n // Build Bing CAPI event\n const capiEvent: CAPIEvent = {\n eventType,\n eventId: event.id,\n eventTime: Math.round((event.timestamp || Date.now()) / 1000),\n adStorageConsent: 'G',\n userData: hashedUserData,\n };\n\n if (eventType === 'custom') {\n capiEvent.eventName = rule?.name || event.name;\n }\n\n if (event.source?.id) {\n capiEvent.eventSourceUrl = event.source.id;\n }\n\n if (Object.keys(customData).length > 0) {\n capiEvent.customData = customData;\n }\n\n const body: CAPIRequestBody = {\n data: [capiEvent],\n dataProvider,\n };\n\n if (continueOnValidationError !== undefined) {\n body.continueOnValidationError = continueOnValidationError;\n }\n\n const endpoint = `${url}${tagId}/events`;\n\n logger.debug('Calling Bing UET CAPI', {\n endpoint,\n method: 'POST',\n eventType: capiEvent.eventType,\n eventName: capiEvent.eventName,\n eventId: capiEvent.eventId,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n });\n\n logger.debug('Bing UET CAPI response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Bing UET CAPI error: ${JSON.stringify(result)}`);\n }\n};\n","import type { UserData } from './types';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Bing UET CAPI user data fields that must be SHA-256 hashed before sending.\n * Only `em` and `ph` are hashable; all other identity fields pass through\n * unhashed (anonymousId, externalId, msclkid, clientIpAddress,\n * clientUserAgent, idfa, gaid).\n * https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi\n */\nconst keysToHash = ['em', 'ph'];\n\n/**\n * Microsoft-specific email normalization:\n * - Trim whitespace\n * - Lowercase\n * - Split at `@`\n * - Remove dots from the user portion\n * - Strip `+alias` suffix from the user portion\n * - Rejoin\n */\nexport function normalizeEmail(value: string): string {\n const trimmed = value.trim().toLowerCase();\n const atIndex = trimmed.lastIndexOf('@');\n if (atIndex < 0) return trimmed;\n\n const user = trimmed.slice(0, atIndex);\n const domain = trimmed.slice(atIndex + 1);\n\n const aliasIndex = user.indexOf('+');\n const beforeAlias = aliasIndex < 0 ? user : user.slice(0, aliasIndex);\n const normalizedUser = beforeAlias.replace(/\\./g, '');\n\n return `${normalizedUser}@${domain}`;\n}\n\nfunction normalizePhone(value: string): string {\n return value.trim();\n}\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\n}\n\nfunction normalizeForKey(key: string, value: string): string {\n if (key === 'em') return normalizeEmail(value);\n if (key === 'ph') return normalizePhone(value);\n return value;\n}\n\nexport async function hashUserData(\n userData: UserData,\n doNotHash: string[] = [],\n): Promise<UserData> {\n const entries = await Promise.all(\n Object.entries(userData).map(async ([key, value]) => {\n if (value === undefined) return [key, value];\n if (shouldBeHashed(key, doNotHash)) {\n const normalized = normalizeForKey(key, String(value));\n return [key, await getHashServer(normalized)];\n }\n return [key, value];\n }),\n );\n\n return Object.fromEntries(entries) as UserData;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\nexport interface Settings {\n accessToken: string;\n tagId: string;\n url?: string;\n doNotHash?: string[];\n user_data?: WalkerOSMapping.Map;\n dataProvider?: string;\n continueOnValidationError?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n eventType?: EventType;\n}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/**\n * Microsoft Advertising (Bing) UET Conversions API\n * https://learn.microsoft.com/en-us/advertising/guides/universal-event-tracking-capi\n */\nexport type EventType = 'pageLoad' | 'custom';\n\nexport type AdStorageConsent = 'G' | 'D';\n\nexport interface CAPIRequestBody {\n data: CAPIEvent[];\n dataProvider?: string;\n continueOnValidationError?: boolean;\n}\n\nexport interface CAPIEvent {\n eventType: EventType;\n eventId?: string;\n eventName?: string;\n eventTime: number;\n eventSourceUrl?: string;\n pageLoadId?: string;\n referrerUrl?: string;\n pageTitle?: string;\n keywords?: string;\n adStorageConsent?: AdStorageConsent;\n userData?: UserData;\n customData?: CustomData;\n}\n\n// User identity fields. Hashable: em, ph. Non-hashable: anonymousId,\n// externalId, msclkid, clientIpAddress, clientUserAgent, idfa, gaid.\nexport interface UserData {\n /** Anonymous ID. Do NOT hash. */\n anonymousId?: string;\n /** External/customer ID. Do NOT hash. */\n externalId?: string;\n /** Email, SHA-256 hashed, normalized (dots/alias stripped, lowercased) */\n em?: string;\n /** Phone number, SHA-256 hashed, trimmed */\n ph?: string;\n /** Microsoft click ID. Do NOT hash. */\n msclkid?: string;\n /** Client IP address (IPv4 or IPv6). Do NOT hash. */\n clientIpAddress?: string;\n /** Client user agent. Do NOT hash. */\n clientUserAgent?: string;\n /** iOS IDFA. Do NOT hash. */\n idfa?: string;\n /** Android advertising ID (GAID). Do NOT hash. */\n gaid?: string;\n}\n\nexport interface CustomData {\n eventCategory?: string;\n eventLabel?: string;\n eventValue?: number;\n searchTerm?: string;\n transactionId?: string;\n value?: number;\n currency?: string;\n items?: ItemData[];\n itemIds?: string[];\n pageType?: string;\n ecommTotalValue?: number;\n ecommCategory?: string;\n hotelData?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface ItemData {\n id?: string;\n quantity?: number;\n price?: number;\n name?: string;\n}\n\nexport interface ResponseBody {\n status?: string;\n requestId?: string;\n}\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationBing from './types';\n\nexport const destinationBing: Destination = {\n type: 'bing',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationBing;\n"],"mappings":"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","names":[]}