@walkeros/server-destination-snapchat 4.0.0-next-1777463920154 → 4.0.0
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.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1 +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,{DestinationSnapchat:()=>types_exports,default:()=>index_default,destinationSnapchat:()=>destinationSnapchat}),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","fn","ln","db","ge","ct","st","zp","country","external_id"];async function hashUserData(userData,doNotHash=[]){const entries=await Promise.all(Object.entries(userData).map(async([key,value])=>void 0===value?[key,value]:function(key,doNotHash=[]){return keysToHash.includes(key)&&!doNotHash.includes(key)}(key,doNotHash)?[key,await(0,import_server_core.getHashServer)(String(value))]:[key,value]));return Object.fromEntries(entries)}var types_exports={},destinationSnapchat={type:"snapchat",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{accessToken:accessToken,pixelId:pixelId}=settings;accessToken||logger.throw("Config settings accessToken missing"),pixelId||logger.throw("Config settings pixelId missing");const settingsConfig={action_source:"WEB",url:"https://tr.snapchat.com/v3/",...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="WEB",doNotHash:doNotHash,url:url="https://tr.snapchat.com/v3/",user_data:user_data,testMode:testMode}=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}):{},eventMappedUserData=(0,import_core.isObject)(eventData.user_data)?eventData.user_data:{},userData={...(0,import_core.isObject)(configData)&&(0,import_core.isObject)(configData.user_data)?configData.user_data:{},...(0,import_core.isObject)(userDataCustom)?userDataCustom:{},...eventMappedUserData},hashedUserData=await hashUserData(userData,doNotHash),customData={};(0,import_core.isObject)(eventData.custom_data)&&Object.assign(customData,eventData.custom_data);for(const[key,value]of Object.entries(eventData))"user_data"!==key&&"custom_data"!==key&&(customData[key]=value);const snapchatEvent={event_name:event.name,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,event_id:event.id,user_data:hashedUserData,custom_data:customData};"WEB"===action_source&&event.source?.url&&(snapchatEvent.event_source_url=event.source.url);const body={data:[snapchatEvent]},endpoint=`${url}${pixelId}/${testMode?"events/validate":"events"}?access_token=${accessToken}`;logger.debug("Calling Snapchat Conversions API",{endpoint:endpoint,method:"POST",eventName:snapchatEvent.event_name,eventId:snapchatEvent.event_id});const sendServerFn=env?.sendServer||import_server_core2.sendServer,result=await sendServerFn(endpoint,JSON.stringify(body));logger.debug("Snapchat API response",{ok:!(0,import_core.isObject)(result)||result.ok}),(0,import_core.isObject)(result)&&!1===result.ok&&logger.throw(`Snapchat API error: ${JSON.stringify(result)}`)}(event,context)},index_default=destinationSnapchat;//# sourceMappingURL=index.js.map
|
|
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,{DestinationSnapchat:()=>types_exports,default:()=>index_default,destinationSnapchat:()=>destinationSnapchat}),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","fn","ln","db","ge","ct","st","zp","country","external_id"];async function hashUserData(userData,doNotHash=[]){const entries=await Promise.all(Object.entries(userData).map(async([key,value])=>void 0===value?[key,value]:function(key,doNotHash=[]){return keysToHash.includes(key)&&!doNotHash.includes(key)}(key,doNotHash)?[key,await(0,import_server_core.getHashServer)(String(value))]:[key,value]));return Object.fromEntries(entries)}var types_exports={},destinationSnapchat={type:"snapchat",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{accessToken:accessToken,pixelId:pixelId}=settings;accessToken||logger.throw("Config settings accessToken missing"),pixelId||logger.throw("Config settings pixelId missing");const settingsConfig={action_source:"WEB",url:"https://tr.snapchat.com/v3/",...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="WEB",doNotHash:doNotHash,url:url="https://tr.snapchat.com/v3/",user_data:user_data,testMode:testMode}=config.settings,eventData=(0,import_core.isObject)(data)?data:{},configData=config.data?await(0,import_core.getMappingValue)(event,config.data,{collector:collector}):{},userDataCustom=user_data?await(0,import_core.getMappingValue)(event,{map:user_data},{collector:collector}):{},eventMappedUserData=(0,import_core.isObject)(eventData.user_data)?eventData.user_data:{},userData={...(0,import_core.isObject)(configData)&&(0,import_core.isObject)(configData.user_data)?configData.user_data:{},...(0,import_core.isObject)(userDataCustom)?userDataCustom:{},...eventMappedUserData},hashedUserData=await hashUserData(userData,doNotHash),customData={};(0,import_core.isObject)(eventData.custom_data)&&Object.assign(customData,eventData.custom_data);for(const[key,value]of Object.entries(eventData))"user_data"!==key&&"custom_data"!==key&&(customData[key]=value);const snapchatEvent={event_name:event.name,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,event_id:event.id,user_data:hashedUserData,custom_data:customData};"WEB"===action_source&&event.source?.url&&(snapchatEvent.event_source_url=event.source.url);const body={data:[snapchatEvent]},endpoint=`${url}${pixelId}/${testMode?"events/validate":"events"}?access_token=${accessToken}`;logger.debug("Calling Snapchat Conversions API",{endpoint:endpoint,method:"POST",eventName:snapchatEvent.event_name,eventId:snapchatEvent.event_id});const sendServerFn=env?.sendServer||import_server_core2.sendServer,result=await sendServerFn(endpoint,JSON.stringify(body));logger.debug("Snapchat API response",{ok:!(0,import_core.isObject)(result)||result.ok}),(0,import_core.isObject)(result)&&!1===result.ok&&logger.throw(`Snapchat API error: ${JSON.stringify(result)}`)}(event,context)},index_default=destinationSnapchat;//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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 DestinationSnapchat from './types';\n\nexport const destinationSnapchat: Destination = {\n type: 'snapchat',\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 destinationSnapchat;\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, pixelId } = settings;\n\n if (!accessToken) logger.throw('Config settings accessToken missing');\n if (!pixelId) logger.throw('Config settings pixelId missing');\n\n const settingsConfig: Settings = {\n action_source: 'WEB',\n url: 'https://tr.snapchat.com/v3/',\n ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CustomData,\n Env,\n PushFn,\n RequestBody,\n Settings,\n SnapchatEvent,\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, collector, env, logger },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'WEB',\n doNotHash,\n url = 'https://tr.snapchat.com/v3/',\n user_data,\n testMode,\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 // Build user_data from three merge sources (priority: later overrides earlier)\n const eventMappedUserData = isObject(eventData.user_data)\n ? (eventData.user_data as UserData)\n : {};\n\n const userData: UserData = {\n // Destination config data\n ...(isObject(configData) && isObject(configData.user_data)\n ? (configData.user_data as UserData)\n : {}),\n // Custom user_data from settings\n ...(isObject(userDataCustom) ? (userDataCustom as UserData) : {}),\n // Event mapping data\n ...eventMappedUserData,\n };\n\n // Hash identity fields\n const hashedUserData = await hashUserData(userData, doNotHash);\n\n // Build custom_data from mapped event data, excluding the user_data key\n // and any explicit custom_data nesting from the mapping\n const customData: CustomData = {};\n if (isObject(eventData.custom_data)) {\n Object.assign(customData, eventData.custom_data);\n }\n for (const [key, value] of Object.entries(eventData)) {\n if (key === 'user_data' || key === 'custom_data') continue;\n customData[key] = value;\n }\n\n // Build Snapchat event\n const snapchatEvent: SnapchatEvent = {\n event_name: event.name,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n event_id: event.id,\n user_data: hashedUserData,\n custom_data: customData,\n };\n\n if (action_source === 'WEB' && event.source?.url) {\n snapchatEvent.event_source_url = event.source.url;\n }\n\n const body: RequestBody = { data: [snapchatEvent] };\n\n const path = testMode ? 'events/validate' : 'events';\n const endpoint = `${url}${pixelId}/${path}?access_token=${accessToken}`;\n\n logger.debug('Calling Snapchat Conversions API', {\n endpoint,\n method: 'POST',\n eventName: snapchatEvent.event_name,\n eventId: snapchatEvent.event_id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body));\n\n logger.debug('Snapchat API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Snapchat API error: ${JSON.stringify(result)}`);\n }\n};\n","import type { UserData } from './types';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Snapchat Conversions API user data fields that must be SHA-256 hashed\n * before sending. Same 11 identity fields as Meta's CAPI.\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nconst keysToHash = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n];\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\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 return [key, await getHashServer(String(value))];\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 pixelId: string;\n url?: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n user_data?: WalkerOSMapping.Map;\n testMode?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\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 * Snapchat Conversions API v3\n * https://businesshelp.snapchat.com/s/article/conversions-api\n */\nexport type ActionSource = 'WEB' | 'MOBILE_APP' | 'OFFLINE';\n\nexport interface RequestBody {\n data: SnapchatEvent[];\n}\n\nexport interface SnapchatEvent {\n event_name: string;\n event_time: number;\n action_source: ActionSource;\n event_source_url?: string;\n event_id?: string;\n user_data: UserData;\n custom_data?: CustomData;\n}\n\n// User identity fields. Hashable: em, ph, fn, ln, db, ge, ct, st, zp, country,\n// external_id. Non-hashable: sc_cookie1, client_ip_address, client_user_agent,\n// sc_click_id, idfv, madid.\nexport interface UserData {\n /** Email, SHA-256 hashed, lowercase trimmed */\n em?: string;\n /** Phone number, SHA-256 hashed, E.164 digits */\n ph?: string;\n /** First name, SHA-256 hashed, lowercase */\n fn?: string;\n /** Last name, SHA-256 hashed, lowercase */\n ln?: string;\n /** Date of birth YYYYMMDD, SHA-256 hashed */\n db?: string;\n /** Gender (m/f), SHA-256 hashed */\n ge?: string;\n /** City, SHA-256 hashed, lowercase */\n ct?: string;\n /** State, SHA-256 hashed, lowercase */\n st?: string;\n /** Zip/postal code, SHA-256 hashed */\n zp?: string;\n /** Country code ISO 3166-1 alpha-2, SHA-256 hashed */\n country?: string;\n /** External/customer ID, SHA-256 hash recommended */\n external_id?: string;\n /** Snap cookie. Do NOT hash. */\n sc_cookie1?: string;\n /** Client IP address (IPv4 or IPv6). Do NOT hash. */\n client_ip_address?: string;\n /** Client user agent. Do NOT hash. */\n client_user_agent?: string;\n /** Snap click ID. Do NOT hash. */\n sc_click_id?: string;\n /** iOS IDFV. Do NOT hash. */\n idfv?: string;\n /** Mobile advertiser ID (IDFA/AAID). Do NOT hash. */\n madid?: string;\n}\n\nexport interface CustomData {\n value?: number;\n currency?: string;\n contents?: ContentItem[];\n item_ids?: string[];\n number_items?: number;\n price?: number;\n cart_total?: number;\n search_string?: string;\n item_category?: string;\n brands?: string[];\n description?: string;\n transaction_id?: string;\n payment_info_available?: number;\n delivery_category?: string;\n sign_up_method?: string;\n level?: string;\n [key: string]: unknown;\n}\n\nexport interface ContentItem {\n id?: string;\n quantity?: number;\n item_price?: number;\n brand?: string;\n}\n\nexport interface ResponseBody {\n status: string;\n request_id?: string;\n}\n\n/**\n * Standard Snapchat event names (UPPERCASE).\n * Custom events via CUSTOM_EVENT_1..5 or arbitrary strings.\n */\nexport type StandardEventName =\n | 'PAGE_VIEW'\n | 'VIEW_CONTENT'\n | 'ADD_CART'\n | 'ADD_TO_WISHLIST'\n | 'START_CHECKOUT'\n | 'ADD_BILLING'\n | 'PURCHASE'\n | 'SIGN_UP'\n | 'SEARCH'\n | 'SAVE'\n | 'SUBSCRIBE'\n | 'COMPLETE_TUTORIAL'\n | 'START_TRIAL'\n | 'AD_CLICK'\n | 'AD_VIEW'\n | 'APP_OPEN'\n | 'LEVEL_COMPLETE'\n | 'INVITE'\n | 'LOGIN'\n | 'SHARE'\n | 'RESERVE'\n | 'ACHIEVEMENT_UNLOCKED'\n | 'SPENT_CREDITS'\n | 'RATE'\n | 'LIST_VIEW'\n | 'CUSTOM_EVENT_1'\n | 'CUSTOM_EVENT_2'\n | 'CUSTOM_EVENT_3'\n | 'CUSTOM_EVENT_4'\n | 'CUSTOM_EVENT_5'\n | (string & {});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,SAAS,UACd,gBAA+B,CAAC,GAChC,QACQ;AACR,QAAM,WAAY,cAAc,YAAY,CAAC;AAC7C,QAAM,EAAE,aAAa,QAAQ,IAAI;AAEjC,MAAI,CAAC,YAAa,QAAO,MAAM,qCAAqC;AACpE,MAAI,CAAC,QAAS,QAAO,MAAM,iCAAiC;AAE5D,QAAM,iBAA2B;AAAA,IAC/B,eAAe;AAAA,IACf,KAAK;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,GAAG,eAAe,UAAU,eAAe;AACtD;;;ACbA,kBAA0C;AAC1C,IAAAA,sBAA2B;;;ACT3B,yBAA8B;AAO9B,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,eAAe,KAAa,YAAsB,CAAC,GAAY;AACtE,SAAO,WAAW,SAAS,GAAG,KAAK,CAAC,UAAU,SAAS,GAAG;AAC5D;AAEA,eAAsB,aACpB,UACA,YAAsB,CAAC,GACJ;AACnB,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,OAAO,QAAQ,QAAQ,EAAE,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM;AACnD,UAAI,UAAU,OAAW,QAAO,CAAC,KAAK,KAAK;AAC3C,UAAI,eAAe,KAAK,SAAS,GAAG;AAClC,eAAO,CAAC,KAAK,UAAM,kCAAc,OAAO,KAAK,CAAC,CAAC;AAAA,MACjD;AACA,aAAO,CAAC,KAAK,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAEA,SAAO,OAAO,YAAY,OAAO;AACnC;;;AD5BO,IAAM,OAAe,eAC1B,OACA,EAAE,QAAQ,MAAM,MAAM,WAAW,KAAK,OAAO,GAC7C;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF,IAAI,OAAO;AAEX,QAAM,gBAAY,sBAAS,IAAI,IAAI,OAAO,CAAC;AAC3C,QAAM,aAAa,OAAO,OACtB,UAAM,6BAAgB,OAAO,OAAO,IAAI,IACxC,CAAC;AACL,QAAM,iBAAiB,YACnB,UAAM,6BAAgB,OAAO,EAAE,KAAK,UAAU,CAAC,IAC/C,CAAC;AAGL,QAAM,0BAAsB,sBAAS,UAAU,SAAS,IACnD,UAAU,YACX,CAAC;AAEL,QAAM,WAAqB;AAAA;AAAA,IAEzB,OAAI,sBAAS,UAAU,SAAK,sBAAS,WAAW,SAAS,IACpD,WAAW,YACZ,CAAC;AAAA;AAAA,IAEL,OAAI,sBAAS,cAAc,IAAK,iBAA8B,CAAC;AAAA;AAAA,IAE/D,GAAG;AAAA,EACL;AAGA,QAAM,iBAAiB,MAAM,aAAa,UAAU,SAAS;AAI7D,QAAM,aAAyB,CAAC;AAChC,UAAI,sBAAS,UAAU,WAAW,GAAG;AACnC,WAAO,OAAO,YAAY,UAAU,WAAW;AAAA,EACjD;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACpD,QAAI,QAAQ,eAAe,QAAQ,cAAe;AAClD,eAAW,GAAG,IAAI;AAAA,EACpB;AAGA,QAAM,gBAA+B;AAAA,IACnC,YAAY,MAAM;AAAA,IAClB,YAAY,KAAK,OAAO,MAAM,aAAa,KAAK,IAAI,KAAK,GAAI;AAAA,IAC7D;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,WAAW;AAAA,IACX,aAAa;AAAA,EACf;AAEA,MAAI,kBAAkB,SAAS,MAAM,QAAQ,KAAK;AAChD,kBAAc,mBAAmB,MAAM,OAAO;AAAA,EAChD;AAEA,QAAM,OAAoB,EAAE,MAAM,CAAC,aAAa,EAAE;AAElD,QAAM,OAAO,WAAW,oBAAoB;AAC5C,QAAM,WAAW,GAAG,GAAG,GAAG,OAAO,IAAI,IAAI,iBAAiB,WAAW;AAErE,SAAO,MAAM,oCAAoC;AAAA,IAC/C;AAAA,IACA,QAAQ;AAAA,IACR,WAAW,cAAc;AAAA,IACzB,SAAS,cAAc;AAAA,EACzB,CAAC;AAED,QAAM,eAAgB,KAAa,cAAc;AACjD,QAAM,SAAS,MAAM,aAAa,UAAU,KAAK,UAAU,IAAI,CAAC;AAEhE,SAAO,MAAM,yBAAyB;AAAA,IACpC,QAAI,sBAAS,MAAM,IAAI,OAAO,KAAK;AAAA,EACrC,CAAC;AAED,UAAI,sBAAS,MAAM,KAAK,OAAO,OAAO,OAAO;AAC3C,WAAO,MAAM,uBAAuB,KAAK,UAAU,MAAM,CAAC,EAAE;AAAA,EAC9D;AACF;;;AErGA;;;AJOO,IAAM,sBAAmC;AAAA,EAC9C,MAAM;AAAA,EAEN,QAAQ,CAAC;AAAA,EAET,MAAM,KAAK,EAAE,QAAQ,eAAe,OAAO,GAAG;AAC5C,UAAM,SAAS,UAAU,eAAe,MAAM;AAC9C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAO,SAAS;AACzB,WAAO,MAAM,KAAK,OAAO,OAAO;AAAA,EAClC;AACF;AAEA,IAAO,gBAAQ;","names":["import_server_core"]}
|
|
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 DestinationSnapchat from './types';\n\nexport const destinationSnapchat: Destination = {\n type: 'snapchat',\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 destinationSnapchat;\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, pixelId } = settings;\n\n if (!accessToken) logger.throw('Config settings accessToken missing');\n if (!pixelId) logger.throw('Config settings pixelId missing');\n\n const settingsConfig: Settings = {\n action_source: 'WEB',\n url: 'https://tr.snapchat.com/v3/',\n ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CustomData,\n Env,\n PushFn,\n RequestBody,\n Settings,\n SnapchatEvent,\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, collector, env, logger },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'WEB',\n doNotHash,\n url = 'https://tr.snapchat.com/v3/',\n user_data,\n testMode,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data, { collector })\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n\n // Build user_data from three merge sources (priority: later overrides earlier)\n const eventMappedUserData = isObject(eventData.user_data)\n ? (eventData.user_data as UserData)\n : {};\n\n const userData: UserData = {\n // Destination config data\n ...(isObject(configData) && isObject(configData.user_data)\n ? (configData.user_data as UserData)\n : {}),\n // Custom user_data from settings\n ...(isObject(userDataCustom) ? (userDataCustom as UserData) : {}),\n // Event mapping data\n ...eventMappedUserData,\n };\n\n // Hash identity fields\n const hashedUserData = await hashUserData(userData, doNotHash);\n\n // Build custom_data from mapped event data, excluding the user_data key\n // and any explicit custom_data nesting from the mapping\n const customData: CustomData = {};\n if (isObject(eventData.custom_data)) {\n Object.assign(customData, eventData.custom_data);\n }\n for (const [key, value] of Object.entries(eventData)) {\n if (key === 'user_data' || key === 'custom_data') continue;\n customData[key] = value;\n }\n\n // Build Snapchat event\n const snapchatEvent: SnapchatEvent = {\n event_name: event.name,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n event_id: event.id,\n user_data: hashedUserData,\n custom_data: customData,\n };\n\n if (action_source === 'WEB' && event.source?.url) {\n snapchatEvent.event_source_url = event.source.url;\n }\n\n const body: RequestBody = { data: [snapchatEvent] };\n\n const path = testMode ? 'events/validate' : 'events';\n const endpoint = `${url}${pixelId}/${path}?access_token=${accessToken}`;\n\n logger.debug('Calling Snapchat Conversions API', {\n endpoint,\n method: 'POST',\n eventName: snapchatEvent.event_name,\n eventId: snapchatEvent.event_id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body));\n\n logger.debug('Snapchat API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Snapchat API error: ${JSON.stringify(result)}`);\n }\n};\n","import type { UserData } from './types';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Snapchat Conversions API user data fields that must be SHA-256 hashed\n * before sending. Same 11 identity fields as Meta's CAPI.\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nconst keysToHash = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n];\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\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 return [key, await getHashServer(String(value))];\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 pixelId: string;\n url?: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n user_data?: WalkerOSMapping.Map;\n testMode?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\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 * Snapchat Conversions API v3\n * https://businesshelp.snapchat.com/s/article/conversions-api\n */\nexport type ActionSource = 'WEB' | 'MOBILE_APP' | 'OFFLINE';\n\nexport interface RequestBody {\n data: SnapchatEvent[];\n}\n\nexport interface SnapchatEvent {\n event_name: string;\n event_time: number;\n action_source: ActionSource;\n event_source_url?: string;\n event_id?: string;\n user_data: UserData;\n custom_data?: CustomData;\n}\n\n// User identity fields. Hashable: em, ph, fn, ln, db, ge, ct, st, zp, country,\n// external_id. Non-hashable: sc_cookie1, client_ip_address, client_user_agent,\n// sc_click_id, idfv, madid.\nexport interface UserData {\n /** Email, SHA-256 hashed, lowercase trimmed */\n em?: string;\n /** Phone number, SHA-256 hashed, E.164 digits */\n ph?: string;\n /** First name, SHA-256 hashed, lowercase */\n fn?: string;\n /** Last name, SHA-256 hashed, lowercase */\n ln?: string;\n /** Date of birth YYYYMMDD, SHA-256 hashed */\n db?: string;\n /** Gender (m/f), SHA-256 hashed */\n ge?: string;\n /** City, SHA-256 hashed, lowercase */\n ct?: string;\n /** State, SHA-256 hashed, lowercase */\n st?: string;\n /** Zip/postal code, SHA-256 hashed */\n zp?: string;\n /** Country code ISO 3166-1 alpha-2, SHA-256 hashed */\n country?: string;\n /** External/customer ID, SHA-256 hash recommended */\n external_id?: string;\n /** Snap cookie. Do NOT hash. */\n sc_cookie1?: string;\n /** Client IP address (IPv4 or IPv6). Do NOT hash. */\n client_ip_address?: string;\n /** Client user agent. Do NOT hash. */\n client_user_agent?: string;\n /** Snap click ID. Do NOT hash. */\n sc_click_id?: string;\n /** iOS IDFV. Do NOT hash. */\n idfv?: string;\n /** Mobile advertiser ID (IDFA/AAID). Do NOT hash. */\n madid?: string;\n}\n\nexport interface CustomData {\n value?: number;\n currency?: string;\n contents?: ContentItem[];\n item_ids?: string[];\n number_items?: number;\n price?: number;\n cart_total?: number;\n search_string?: string;\n item_category?: string;\n brands?: string[];\n description?: string;\n transaction_id?: string;\n payment_info_available?: number;\n delivery_category?: string;\n sign_up_method?: string;\n level?: string;\n [key: string]: unknown;\n}\n\nexport interface ContentItem {\n id?: string;\n quantity?: number;\n item_price?: number;\n brand?: string;\n}\n\nexport interface ResponseBody {\n status: string;\n request_id?: string;\n}\n\n/**\n * Standard Snapchat event names (UPPERCASE).\n * Custom events via CUSTOM_EVENT_1..5 or arbitrary strings.\n */\nexport type StandardEventName =\n | 'PAGE_VIEW'\n | 'VIEW_CONTENT'\n | 'ADD_CART'\n | 'ADD_TO_WISHLIST'\n | 'START_CHECKOUT'\n | 'ADD_BILLING'\n | 'PURCHASE'\n | 'SIGN_UP'\n | 'SEARCH'\n | 'SAVE'\n | 'SUBSCRIBE'\n | 'COMPLETE_TUTORIAL'\n | 'START_TRIAL'\n | 'AD_CLICK'\n | 'AD_VIEW'\n | 'APP_OPEN'\n | 'LEVEL_COMPLETE'\n | 'INVITE'\n | 'LOGIN'\n | 'SHARE'\n | 'RESERVE'\n | 'ACHIEVEMENT_UNLOCKED'\n | 'SPENT_CREDITS'\n | 'RATE'\n | 'LIST_VIEW'\n | 'CUSTOM_EVENT_1'\n | 'CUSTOM_EVENT_2'\n | 'CUSTOM_EVENT_3'\n | 'CUSTOM_EVENT_4'\n | 'CUSTOM_EVENT_5'\n | (string & {});\n"],"mappings":"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","names":["import_server_core"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getMappingValue,isObject}from"@walkeros/core";import{sendServer}from"@walkeros/server-core";import{getHashServer}from"@walkeros/server-core";var keysToHash=["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id"];async function hashUserData(userData,doNotHash=[]){const entries=await Promise.all(Object.entries(userData).map(async([key,value])=>void 0===value?[key,value]:function(key,doNotHash=[]){return keysToHash.includes(key)&&!doNotHash.includes(key)}(key,doNotHash)?[key,await getHashServer(String(value))]:[key,value]));return Object.fromEntries(entries)}var types_exports={},destinationSnapchat={type:"snapchat",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{accessToken:accessToken,pixelId:pixelId}=settings;accessToken||logger.throw("Config settings accessToken missing"),pixelId||logger.throw("Config settings pixelId missing");const settingsConfig={action_source:"WEB",url:"https://tr.snapchat.com/v3/",...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="WEB",doNotHash:doNotHash,url:url="https://tr.snapchat.com/v3/",user_data:user_data,testMode:testMode}=config.settings,eventData=isObject(data)?data:{},configData=config.data?await getMappingValue(event,config.data):{},userDataCustom=user_data?await getMappingValue(event,{map:user_data}):{},eventMappedUserData=isObject(eventData.user_data)?eventData.user_data:{},userData={...isObject(configData)&&isObject(configData.user_data)?configData.user_data:{},...isObject(userDataCustom)?userDataCustom:{},...eventMappedUserData},hashedUserData=await hashUserData(userData,doNotHash),customData={};isObject(eventData.custom_data)&&Object.assign(customData,eventData.custom_data);for(const[key,value]of Object.entries(eventData))"user_data"!==key&&"custom_data"!==key&&(customData[key]=value);const snapchatEvent={event_name:event.name,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,event_id:event.id,user_data:hashedUserData,custom_data:customData};"WEB"===action_source&&event.source?.url&&(snapchatEvent.event_source_url=event.source.url);const body={data:[snapchatEvent]},endpoint=`${url}${pixelId}/${testMode?"events/validate":"events"}?access_token=${accessToken}`;logger.debug("Calling Snapchat Conversions API",{endpoint:endpoint,method:"POST",eventName:snapchatEvent.event_name,eventId:snapchatEvent.event_id});const sendServerFn=env?.sendServer||sendServer,result=await sendServerFn(endpoint,JSON.stringify(body));logger.debug("Snapchat API response",{ok:!isObject(result)||result.ok}),isObject(result)&&!1===result.ok&&logger.throw(`Snapchat API error: ${JSON.stringify(result)}`)}(event,context)},index_default=destinationSnapchat;export{types_exports as DestinationSnapchat,index_default as default,destinationSnapchat};//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import{getMappingValue,isObject}from"@walkeros/core";import{sendServer}from"@walkeros/server-core";import{getHashServer}from"@walkeros/server-core";var keysToHash=["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id"];async function hashUserData(userData,doNotHash=[]){const entries=await Promise.all(Object.entries(userData).map(async([key,value])=>void 0===value?[key,value]:function(key,doNotHash=[]){return keysToHash.includes(key)&&!doNotHash.includes(key)}(key,doNotHash)?[key,await getHashServer(String(value))]:[key,value]));return Object.fromEntries(entries)}var types_exports={},destinationSnapchat={type:"snapchat",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{accessToken:accessToken,pixelId:pixelId}=settings;accessToken||logger.throw("Config settings accessToken missing"),pixelId||logger.throw("Config settings pixelId missing");const settingsConfig={action_source:"WEB",url:"https://tr.snapchat.com/v3/",...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await async function(event,{config:config,rule:rule,data:data,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="WEB",doNotHash:doNotHash,url:url="https://tr.snapchat.com/v3/",user_data:user_data,testMode:testMode}=config.settings,eventData=isObject(data)?data:{},configData=config.data?await getMappingValue(event,config.data,{collector:collector}):{},userDataCustom=user_data?await getMappingValue(event,{map:user_data},{collector:collector}):{},eventMappedUserData=isObject(eventData.user_data)?eventData.user_data:{},userData={...isObject(configData)&&isObject(configData.user_data)?configData.user_data:{},...isObject(userDataCustom)?userDataCustom:{},...eventMappedUserData},hashedUserData=await hashUserData(userData,doNotHash),customData={};isObject(eventData.custom_data)&&Object.assign(customData,eventData.custom_data);for(const[key,value]of Object.entries(eventData))"user_data"!==key&&"custom_data"!==key&&(customData[key]=value);const snapchatEvent={event_name:event.name,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,event_id:event.id,user_data:hashedUserData,custom_data:customData};"WEB"===action_source&&event.source?.url&&(snapchatEvent.event_source_url=event.source.url);const body={data:[snapchatEvent]},endpoint=`${url}${pixelId}/${testMode?"events/validate":"events"}?access_token=${accessToken}`;logger.debug("Calling Snapchat Conversions API",{endpoint:endpoint,method:"POST",eventName:snapchatEvent.event_name,eventId:snapchatEvent.event_id});const sendServerFn=env?.sendServer||sendServer,result=await sendServerFn(endpoint,JSON.stringify(body));logger.debug("Snapchat API response",{ok:!isObject(result)||result.ok}),isObject(result)&&!1===result.ok&&logger.throw(`Snapchat API error: ${JSON.stringify(result)}`)}(event,context)},index_default=destinationSnapchat;export{types_exports as DestinationSnapchat,index_default as default,destinationSnapchat};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +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, pixelId } = settings;\n\n if (!accessToken) logger.throw('Config settings accessToken missing');\n if (!pixelId) logger.throw('Config settings pixelId missing');\n\n const settingsConfig: Settings = {\n action_source: 'WEB',\n url: 'https://tr.snapchat.com/v3/',\n ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CustomData,\n Env,\n PushFn,\n RequestBody,\n Settings,\n SnapchatEvent,\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, collector, env, logger },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'WEB',\n doNotHash,\n url = 'https://tr.snapchat.com/v3/',\n user_data,\n testMode,\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 // Build user_data from three merge sources (priority: later overrides earlier)\n const eventMappedUserData = isObject(eventData.user_data)\n ? (eventData.user_data as UserData)\n : {};\n\n const userData: UserData = {\n // Destination config data\n ...(isObject(configData) && isObject(configData.user_data)\n ? (configData.user_data as UserData)\n : {}),\n // Custom user_data from settings\n ...(isObject(userDataCustom) ? (userDataCustom as UserData) : {}),\n // Event mapping data\n ...eventMappedUserData,\n };\n\n // Hash identity fields\n const hashedUserData = await hashUserData(userData, doNotHash);\n\n // Build custom_data from mapped event data, excluding the user_data key\n // and any explicit custom_data nesting from the mapping\n const customData: CustomData = {};\n if (isObject(eventData.custom_data)) {\n Object.assign(customData, eventData.custom_data);\n }\n for (const [key, value] of Object.entries(eventData)) {\n if (key === 'user_data' || key === 'custom_data') continue;\n customData[key] = value;\n }\n\n // Build Snapchat event\n const snapchatEvent: SnapchatEvent = {\n event_name: event.name,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n event_id: event.id,\n user_data: hashedUserData,\n custom_data: customData,\n };\n\n if (action_source === 'WEB' && event.source?.url) {\n snapchatEvent.event_source_url = event.source.url;\n }\n\n const body: RequestBody = { data: [snapchatEvent] };\n\n const path = testMode ? 'events/validate' : 'events';\n const endpoint = `${url}${pixelId}/${path}?access_token=${accessToken}`;\n\n logger.debug('Calling Snapchat Conversions API', {\n endpoint,\n method: 'POST',\n eventName: snapchatEvent.event_name,\n eventId: snapchatEvent.event_id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body));\n\n logger.debug('Snapchat API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Snapchat API error: ${JSON.stringify(result)}`);\n }\n};\n","import type { UserData } from './types';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Snapchat Conversions API user data fields that must be SHA-256 hashed\n * before sending. Same 11 identity fields as Meta's CAPI.\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nconst keysToHash = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n];\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\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 return [key, await getHashServer(String(value))];\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 pixelId: string;\n url?: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n user_data?: WalkerOSMapping.Map;\n testMode?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\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 * Snapchat Conversions API v3\n * https://businesshelp.snapchat.com/s/article/conversions-api\n */\nexport type ActionSource = 'WEB' | 'MOBILE_APP' | 'OFFLINE';\n\nexport interface RequestBody {\n data: SnapchatEvent[];\n}\n\nexport interface SnapchatEvent {\n event_name: string;\n event_time: number;\n action_source: ActionSource;\n event_source_url?: string;\n event_id?: string;\n user_data: UserData;\n custom_data?: CustomData;\n}\n\n// User identity fields. Hashable: em, ph, fn, ln, db, ge, ct, st, zp, country,\n// external_id. Non-hashable: sc_cookie1, client_ip_address, client_user_agent,\n// sc_click_id, idfv, madid.\nexport interface UserData {\n /** Email, SHA-256 hashed, lowercase trimmed */\n em?: string;\n /** Phone number, SHA-256 hashed, E.164 digits */\n ph?: string;\n /** First name, SHA-256 hashed, lowercase */\n fn?: string;\n /** Last name, SHA-256 hashed, lowercase */\n ln?: string;\n /** Date of birth YYYYMMDD, SHA-256 hashed */\n db?: string;\n /** Gender (m/f), SHA-256 hashed */\n ge?: string;\n /** City, SHA-256 hashed, lowercase */\n ct?: string;\n /** State, SHA-256 hashed, lowercase */\n st?: string;\n /** Zip/postal code, SHA-256 hashed */\n zp?: string;\n /** Country code ISO 3166-1 alpha-2, SHA-256 hashed */\n country?: string;\n /** External/customer ID, SHA-256 hash recommended */\n external_id?: string;\n /** Snap cookie. Do NOT hash. */\n sc_cookie1?: string;\n /** Client IP address (IPv4 or IPv6). Do NOT hash. */\n client_ip_address?: string;\n /** Client user agent. Do NOT hash. */\n client_user_agent?: string;\n /** Snap click ID. Do NOT hash. */\n sc_click_id?: string;\n /** iOS IDFV. Do NOT hash. */\n idfv?: string;\n /** Mobile advertiser ID (IDFA/AAID). Do NOT hash. */\n madid?: string;\n}\n\nexport interface CustomData {\n value?: number;\n currency?: string;\n contents?: ContentItem[];\n item_ids?: string[];\n number_items?: number;\n price?: number;\n cart_total?: number;\n search_string?: string;\n item_category?: string;\n brands?: string[];\n description?: string;\n transaction_id?: string;\n payment_info_available?: number;\n delivery_category?: string;\n sign_up_method?: string;\n level?: string;\n [key: string]: unknown;\n}\n\nexport interface ContentItem {\n id?: string;\n quantity?: number;\n item_price?: number;\n brand?: string;\n}\n\nexport interface ResponseBody {\n status: string;\n request_id?: string;\n}\n\n/**\n * Standard Snapchat event names (UPPERCASE).\n * Custom events via CUSTOM_EVENT_1..5 or arbitrary strings.\n */\nexport type StandardEventName =\n | 'PAGE_VIEW'\n | 'VIEW_CONTENT'\n | 'ADD_CART'\n | 'ADD_TO_WISHLIST'\n | 'START_CHECKOUT'\n | 'ADD_BILLING'\n | 'PURCHASE'\n | 'SIGN_UP'\n | 'SEARCH'\n | 'SAVE'\n | 'SUBSCRIBE'\n | 'COMPLETE_TUTORIAL'\n | 'START_TRIAL'\n | 'AD_CLICK'\n | 'AD_VIEW'\n | 'APP_OPEN'\n | 'LEVEL_COMPLETE'\n | 'INVITE'\n | 'LOGIN'\n | 'SHARE'\n | 'RESERVE'\n | 'ACHIEVEMENT_UNLOCKED'\n | 'SPENT_CREDITS'\n | 'RATE'\n | 'LIST_VIEW'\n | 'CUSTOM_EVENT_1'\n | 'CUSTOM_EVENT_2'\n | 'CUSTOM_EVENT_3'\n | 'CUSTOM_EVENT_4'\n | 'CUSTOM_EVENT_5'\n | (string & {});\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationSnapchat from './types';\n\nexport const destinationSnapchat: Destination = {\n type: 'snapchat',\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 destinationSnapchat;\n"],"mappings":"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","names":[]}
|
|
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, pixelId } = settings;\n\n if (!accessToken) logger.throw('Config settings accessToken missing');\n if (!pixelId) logger.throw('Config settings pixelId missing');\n\n const settingsConfig: Settings = {\n action_source: 'WEB',\n url: 'https://tr.snapchat.com/v3/',\n ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CustomData,\n Env,\n PushFn,\n RequestBody,\n Settings,\n SnapchatEvent,\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, collector, env, logger },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'WEB',\n doNotHash,\n url = 'https://tr.snapchat.com/v3/',\n user_data,\n testMode,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data, { collector })\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n\n // Build user_data from three merge sources (priority: later overrides earlier)\n const eventMappedUserData = isObject(eventData.user_data)\n ? (eventData.user_data as UserData)\n : {};\n\n const userData: UserData = {\n // Destination config data\n ...(isObject(configData) && isObject(configData.user_data)\n ? (configData.user_data as UserData)\n : {}),\n // Custom user_data from settings\n ...(isObject(userDataCustom) ? (userDataCustom as UserData) : {}),\n // Event mapping data\n ...eventMappedUserData,\n };\n\n // Hash identity fields\n const hashedUserData = await hashUserData(userData, doNotHash);\n\n // Build custom_data from mapped event data, excluding the user_data key\n // and any explicit custom_data nesting from the mapping\n const customData: CustomData = {};\n if (isObject(eventData.custom_data)) {\n Object.assign(customData, eventData.custom_data);\n }\n for (const [key, value] of Object.entries(eventData)) {\n if (key === 'user_data' || key === 'custom_data') continue;\n customData[key] = value;\n }\n\n // Build Snapchat event\n const snapchatEvent: SnapchatEvent = {\n event_name: event.name,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n event_id: event.id,\n user_data: hashedUserData,\n custom_data: customData,\n };\n\n if (action_source === 'WEB' && event.source?.url) {\n snapchatEvent.event_source_url = event.source.url;\n }\n\n const body: RequestBody = { data: [snapchatEvent] };\n\n const path = testMode ? 'events/validate' : 'events';\n const endpoint = `${url}${pixelId}/${path}?access_token=${accessToken}`;\n\n logger.debug('Calling Snapchat Conversions API', {\n endpoint,\n method: 'POST',\n eventName: snapchatEvent.event_name,\n eventId: snapchatEvent.event_id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body));\n\n logger.debug('Snapchat API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Snapchat API error: ${JSON.stringify(result)}`);\n }\n};\n","import type { UserData } from './types';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Snapchat Conversions API user data fields that must be SHA-256 hashed\n * before sending. Same 11 identity fields as Meta's CAPI.\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nconst keysToHash = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n];\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\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 return [key, await getHashServer(String(value))];\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 pixelId: string;\n url?: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n user_data?: WalkerOSMapping.Map;\n testMode?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\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 * Snapchat Conversions API v3\n * https://businesshelp.snapchat.com/s/article/conversions-api\n */\nexport type ActionSource = 'WEB' | 'MOBILE_APP' | 'OFFLINE';\n\nexport interface RequestBody {\n data: SnapchatEvent[];\n}\n\nexport interface SnapchatEvent {\n event_name: string;\n event_time: number;\n action_source: ActionSource;\n event_source_url?: string;\n event_id?: string;\n user_data: UserData;\n custom_data?: CustomData;\n}\n\n// User identity fields. Hashable: em, ph, fn, ln, db, ge, ct, st, zp, country,\n// external_id. Non-hashable: sc_cookie1, client_ip_address, client_user_agent,\n// sc_click_id, idfv, madid.\nexport interface UserData {\n /** Email, SHA-256 hashed, lowercase trimmed */\n em?: string;\n /** Phone number, SHA-256 hashed, E.164 digits */\n ph?: string;\n /** First name, SHA-256 hashed, lowercase */\n fn?: string;\n /** Last name, SHA-256 hashed, lowercase */\n ln?: string;\n /** Date of birth YYYYMMDD, SHA-256 hashed */\n db?: string;\n /** Gender (m/f), SHA-256 hashed */\n ge?: string;\n /** City, SHA-256 hashed, lowercase */\n ct?: string;\n /** State, SHA-256 hashed, lowercase */\n st?: string;\n /** Zip/postal code, SHA-256 hashed */\n zp?: string;\n /** Country code ISO 3166-1 alpha-2, SHA-256 hashed */\n country?: string;\n /** External/customer ID, SHA-256 hash recommended */\n external_id?: string;\n /** Snap cookie. Do NOT hash. */\n sc_cookie1?: string;\n /** Client IP address (IPv4 or IPv6). Do NOT hash. */\n client_ip_address?: string;\n /** Client user agent. Do NOT hash. */\n client_user_agent?: string;\n /** Snap click ID. Do NOT hash. */\n sc_click_id?: string;\n /** iOS IDFV. Do NOT hash. */\n idfv?: string;\n /** Mobile advertiser ID (IDFA/AAID). Do NOT hash. */\n madid?: string;\n}\n\nexport interface CustomData {\n value?: number;\n currency?: string;\n contents?: ContentItem[];\n item_ids?: string[];\n number_items?: number;\n price?: number;\n cart_total?: number;\n search_string?: string;\n item_category?: string;\n brands?: string[];\n description?: string;\n transaction_id?: string;\n payment_info_available?: number;\n delivery_category?: string;\n sign_up_method?: string;\n level?: string;\n [key: string]: unknown;\n}\n\nexport interface ContentItem {\n id?: string;\n quantity?: number;\n item_price?: number;\n brand?: string;\n}\n\nexport interface ResponseBody {\n status: string;\n request_id?: string;\n}\n\n/**\n * Standard Snapchat event names (UPPERCASE).\n * Custom events via CUSTOM_EVENT_1..5 or arbitrary strings.\n */\nexport type StandardEventName =\n | 'PAGE_VIEW'\n | 'VIEW_CONTENT'\n | 'ADD_CART'\n | 'ADD_TO_WISHLIST'\n | 'START_CHECKOUT'\n | 'ADD_BILLING'\n | 'PURCHASE'\n | 'SIGN_UP'\n | 'SEARCH'\n | 'SAVE'\n | 'SUBSCRIBE'\n | 'COMPLETE_TUTORIAL'\n | 'START_TRIAL'\n | 'AD_CLICK'\n | 'AD_VIEW'\n | 'APP_OPEN'\n | 'LEVEL_COMPLETE'\n | 'INVITE'\n | 'LOGIN'\n | 'SHARE'\n | 'RESERVE'\n | 'ACHIEVEMENT_UNLOCKED'\n | 'SPENT_CREDITS'\n | 'RATE'\n | 'LIST_VIEW'\n | 'CUSTOM_EVENT_1'\n | 'CUSTOM_EVENT_2'\n | 'CUSTOM_EVENT_3'\n | 'CUSTOM_EVENT_4'\n | 'CUSTOM_EVENT_5'\n | (string & {});\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationSnapchat from './types';\n\nexport const destinationSnapchat: Destination = {\n type: 'snapchat',\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 destinationSnapchat;\n"],"mappings":"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","names":[]}
|
package/dist/walkerOS.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/server-destination-snapchat",
|
|
3
3
|
"description": "Snapchat Conversions API server destination for walkerOS",
|
|
4
|
-
"version": "4.0.0
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"update": "npx npm-check-updates -u && npm update"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@walkeros/core": "4.0.0
|
|
38
|
-
"@walkeros/server-core": "4.0.0
|
|
37
|
+
"@walkeros/core": "4.0.0",
|
|
38
|
+
"@walkeros/server-core": "4.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@walkeros/collector": "4.0.0
|
|
41
|
+
"@walkeros/collector": "4.0.0"
|
|
42
42
|
},
|
|
43
43
|
"repository": {
|
|
44
44
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|