@walkeros/server-destination-snapchat 3.4.2 → 4.0.0-next-1777463920154
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/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/examples/index.js +20 -16
- package/dist/examples/index.mjs +20 -16
- 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 +21 -59
- package/package.json +4 -4
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,s=(e,a)=>{for(var r in a)t(e,r,{get:a[r],enumerable:!0})},o={};s(o,{examples:()=>E,schemas:()=>i}),module.exports=(e=o,((e,s,o,i)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let c of r(s))n.call(e,c)||c===o||t(e,c,{get:()=>s[c],enumerable:!(i=a(s,c))||i.enumerable});return e})(t({},"__esModule",{value:!0}),e));var i={};s(i,{MappingSchema:()=>u,SettingsSchema:()=>p,StandardEventNameSchema:()=>l,mapping:()=>v,settings:()=>_});var c=require("@walkeros/core/dev"),d=require("@walkeros/core/dev"),p=d.z.object({accessToken:d.z.string().min(1).describe("Long-lived Conversions API access token from Snapchat Ads Manager"),pixelId:d.z.string().min(1).describe("Snap Pixel ID"),url:d.z.string().url().describe("Custom Conversions API base URL (default https://tr.snapchat.com/v3/)").optional(),action_source:d.z.enum(["WEB","MOBILE_APP","OFFLINE"]).describe("Event action source (default WEB)").optional(),doNotHash:d.z.array(d.z.string()).describe("User data fields to skip hashing (like ['em', 'ph'])").optional(),user_data:d.z.record(d.z.string(),d.z.string()).describe("Mapping for user data fields (like { em: 'user.email' })").optional(),testMode:d.z.boolean().describe("When true, sends events to /events/validate instead of /events for testing").optional()}),u=require("@walkeros/core/dev").z.object({}),m=require("@walkeros/core/dev"),l=m.z.union([m.z.enum(["PAGE_VIEW","VIEW_CONTENT","ADD_CART","ADD_TO_WISHLIST","START_CHECKOUT","ADD_BILLING","PURCHASE","SIGN_UP","SEARCH","SAVE","SUBSCRIBE","COMPLETE_TUTORIAL","START_TRIAL","AD_CLICK","AD_VIEW","APP_OPEN","LEVEL_COMPLETE","INVITE","LOGIN","SHARE","RESERVE","ACHIEVEMENT_UNLOCKED","SPENT_CREDITS","RATE","LIST_VIEW","CUSTOM_EVENT_1","CUSTOM_EVENT_2","CUSTOM_EVENT_3","CUSTOM_EVENT_4","CUSTOM_EVENT_5"]),m.z.string()]),_=(0,c.zodToSchema)(p),v=(0,c.zodToSchema)(u),E={};s(E,{env:()=>S,step:()=>f});var S={};s(S,{push:()=>h,simulation:()=>b});var h={sendServer:async()=>({ok:!0,data:{status:"OK",request_id:"mock-123"}})},b=["sendServer"],f={};s(f,{addToCart:()=>T,lead:()=>w,pageView:()=>O,purchase:()=>A});var g=require("@walkeros/core"),y="https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t",A={title:"Purchase",description:"A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.",in:(0,g.getEvent)("order complete",{id:"e1f2a3b4c5d60001",timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",name:"Widget Pro",price:124.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com/checkout/complete"}}),mapping:{name:"PURCHASE",data:{map:{custom_data:{map:{value:"data.total",currency:{key:"data.currency",value:"EUR"},transaction_id:"data.id",contents:{loop:["nested",{condition:e=>(0,g.isObject)(e)&&"product"===e.entity,map:{id:"data.id",item_price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}},user_data:{map:{external_id:"user.id"}}}}},out:[["sendServer",y,JSON.stringify({data:[{event_name:"PURCHASE",event_time:1700000900,action_source:"WEB",event_id:"e1f2a3b4c5d60001",user_data:{external_id:"fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8"},custom_data:{value:249.99,currency:"EUR",transaction_id:"ORD-300",contents:[{id:"SKU-A1",item_price:124.99,quantity:2}]},event_source_url:"https://shop.example.com/checkout/complete"}]})]]},T={title:"Add to cart",description:"A product add is sent to Snapchat as an ADD_CART conversion with value and product details.",in:(0,g.getEvent)("product add",{id:"e1f2a3b4c5d60002",timestamp:1700000901e3,data:{id:"SKU-B2",name:"Running Shoes",price:89.99,color:"blue"},nested:[{entity:"product",data:{id:"SKU-B2",name:"Running Shoes",price:89.99,quantity:1}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/running-shoes"}}),mapping:{name:"ADD_CART",data:{map:{custom_data:{map:{value:"data.price",currency:{value:"EUR"},contents:{loop:["nested",{condition:e=>(0,g.isObject)(e)&&"product"===e.entity,map:{id:"data.id",item_price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}}}},out:[["sendServer",y,JSON.stringify({data:[{event_name:"ADD_CART",event_time:1700000901,action_source:"WEB",event_id:"e1f2a3b4c5d60002",user_data:{},custom_data:{value:89.99,currency:"EUR",contents:[{id:"SKU-B2",item_price:89.99,quantity:1}]},event_source_url:"https://shop.example.com/products/running-shoes"}]})]]},O={title:"Page view",description:"A page view is forwarded to Snapchat with the event source URL and no extra custom data.",in:(0,g.getEvent)("page view",{id:"e1f2a3b4c5d60003",timestamp:1700000902e3,source:{type:"browser",platform:"web",url:"https://example.com/docs/"}}),mapping:void 0,out:[["sendServer",y,JSON.stringify({data:[{event_name:"page view",event_time:1700000902,action_source:"WEB",event_id:"e1f2a3b4c5d60003",user_data:{},custom_data:{},event_source_url:"https://example.com/docs/"}]})]]},w={title:"Sign up",description:"A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.",in:(0,g.getEvent)("form submit",{id:"e1f2a3b4c5d60004",timestamp:1700000903e3,data:{type:"newsletter"},user:{email:"user@example.com"},source:{type:"browser",platform:"web",url:"https://example.com/contact"}}),mapping:{name:"SIGN_UP",data:{map:{user_data:{map:{em:"user.email"}},custom_data:{map:{sign_up_method:{value:"newsletter"}}}}}},out:[["sendServer",y,JSON.stringify({data:[{event_name:"SIGN_UP",event_time:1700000903,action_source:"WEB",event_id:"e1f2a3b4c5d60004",user_data:{em:"b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514"},custom_data:{sign_up_method:"newsletter"},event_source_url:"https://example.com/contact"}]})]]};//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Long-lived Conversions API access token from Snapchat Ads Manager',\n ),\n pixelId: z.string().min(1).describe('Snap Pixel ID'),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Conversions API base URL (default https://tr.snapchat.com/v3/)',\n )\n .optional(),\n action_source: z\n .enum(['WEB', 'MOBILE_APP', 'OFFLINE'])\n .describe('Event action source (default WEB)')\n .optional(),\n doNotHash: z\n .array(z.string())\n .describe(\"User data fields to skip hashing (like ['em', 'ph'])\")\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\"Mapping for user data fields (like { em: 'user.email' })\")\n .optional(),\n testMode: z\n .boolean()\n .describe(\n 'When true, sends events to /events/validate instead of /events for testing',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Snapchat Conversions API Mapping Schema\n * Snapchat CAPI has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Snapchat Conversions API event names (UPPERCASE).\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nexport const StandardEventNameSchema = z.union([\n z.enum([\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 ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Snapchat Conversions API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: {\n status: 'OK',\n request_id: 'mock-123',\n },\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Snapchat Conversions API events without making\n * actual HTTP requests to Snapchat's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Snapchat Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is `${settings.url}${settings.pixelId}/${path}?access_token=${settings.accessToken}`\n * with `path` = `events` (or `events/validate` when `testMode` is set),\n * and `body` is the JSON-stringified `{ data: [snapchatEvent] }` payload.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = 'p1x3l1d'`,\n * so every endpoint resolves to:\n * https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t\n *\n * Body fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * 1. event_name\n * 2. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 3. action_source (default 'WEB')\n * 4. event_id\n * 5. user_data (hashed per Snapchat's PII requirements)\n * 6. custom_data (mapped event data, excluding user_data/custom_data keys)\n * 7. event_source_url (appended last when action_source === 'WEB')\n */\nconst ENDPOINT =\n 'https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.',\n in: getEvent('order complete', {\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'server',\n id: 'https://shop.example.com/checkout/complete',\n previous_id: '',\n },\n }),\n mapping: {\n name: 'PURCHASE',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.total',\n currency: { key: 'data.currency', value: 'EUR' },\n transaction_id: 'data.id',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n user_data: {\n map: {\n external_id: 'user.id',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'PURCHASE',\n event_time: 1700000900,\n action_source: 'WEB',\n event_id: '1700000900000-gr0up-1',\n user_data: {\n external_id:\n 'fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8',\n },\n custom_data: {\n value: 249.99,\n currency: 'EUR',\n transaction_id: 'ORD-300',\n contents: [{ id: 'SKU-A1', item_price: 124.99, quantity: 2 }],\n },\n event_source_url: 'https://shop.example.com/checkout/complete',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add is sent to Snapchat as an ADD_CART conversion with value and product details.',\n in: getEvent('product add', {\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n color: 'blue',\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'server',\n id: 'https://shop.example.com/products/running-shoes',\n previous_id: '',\n },\n }),\n mapping: {\n name: 'ADD_CART',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.price',\n currency: { value: 'EUR' },\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'ADD_CART',\n event_time: 1700000901,\n action_source: 'WEB',\n event_id: '1700000901000-gr0up-1',\n user_data: {},\n custom_data: {\n value: 89.99,\n currency: 'EUR',\n contents: [{ id: 'SKU-B2', item_price: 89.99, quantity: 1 }],\n },\n event_source_url: 'https://shop.example.com/products/running-shoes',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is forwarded to Snapchat with the event source URL and no extra custom data.',\n in: getEvent('page view', {\n timestamp: 1700000902000,\n source: {\n type: 'server',\n id: 'https://example.com/docs/',\n previous_id: '',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'page view',\n event_time: 1700000902,\n action_source: 'WEB',\n event_id: '1700000902000-gr0up-1',\n user_data: {},\n custom_data: {},\n event_source_url: 'https://example.com/docs/',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Sign up',\n description:\n 'A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.',\n in: getEvent('form submit', {\n timestamp: 1700000903000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'server',\n id: 'https://example.com/contact',\n previous_id: '',\n },\n }),\n mapping: {\n name: 'SIGN_UP',\n data: {\n map: {\n user_data: {\n map: {\n em: 'user.email',\n },\n },\n custom_data: {\n map: {\n sign_up_method: { value: 'newsletter' },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'SIGN_UP',\n event_time: 1700000903,\n action_source: 'WEB',\n event_id: '1700000903000-gr0up-1',\n user_data: {\n // sha256('user@example.com')\n em: 'b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514',\n },\n custom_data: {\n sign_up_method: 'newsletter',\n },\n event_source_url: 'https://example.com/contact',\n },\n ],\n }),\n ],\n ],\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,cAA4B;;;ACA5B,iBAAkB;AAEX,IAAM,iBAAiB,aAAE,OAAO;AAAA,EACrC,aAAa,aACV,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,SAAS,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,eAAe;AAAA,EACnD,KAAK,aACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAe,aACZ,KAAK,CAAC,OAAO,cAAc,SAAS,CAAC,EACrC,SAAS,mCAAmC,EAC5C,SAAS;AAAA,EACZ,WAAW,aACR,MAAM,aAAE,OAAO,CAAC,EAChB,SAAS,sDAAsD,EAC/D,SAAS;AAAA,EACZ,WAAW,aACR,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,CAAC,EAC7B,SAAS,0DAA0D,EACnE,SAAS;AAAA,EACZ,UAAU,aACP,QAAQ,EACR;AAAA,IACC;AAAA,EACF,EACC,SAAS;AACd,CAAC;;;ACnCD,IAAAC,cAAkB;AAMX,IAAM,gBAAgB,cAAE,OAAO,CAAC,CAAC;;;ACNxC,IAAAC,cAAkB;AAMX,IAAM,0BAA0B,cAAE,MAAM;AAAA,EAC7C,cAAE,KAAK;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA,EACD,cAAE,OAAO;AAAA;AACX,CAAC;;;AH9BM,IAAM,eAAW,yBAAY,cAAc;AAC3C,IAAM,cAAU,yBAAY,aAAa;;;AIXhD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAiBA,IAAM,iBAAiC,aAAa;AAAA,EAClD,IAAI;AAAA,EACJ,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAQO,IAAM,OAAY;AAAA,EACvB,YAAY;AACd;AAEO,IAAM,aAAa,CAAC,YAAY;;;ACnCvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAmC;AAwBnC,IAAM,WACJ;AAEK,IAAM,WAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,kBAAkB;AAAA,IAC7B,WAAW;AAAA,IACX,MAAM,EAAE,IAAI,WAAW,OAAO,QAAQ,UAAU,MAAM;AAAA,IACtD,QAAQ;AAAA,MACN;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,EAAE,IAAI,UAAU,MAAM,cAAc,OAAO,QAAQ,UAAU,EAAE;AAAA,MACvE;AAAA,IACF;AAAA,IACA,MAAM,EAAE,IAAI,YAAY,QAAQ,aAAa;AAAA,IAC7C,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,aAAa;AAAA,UACX,KAAK;AAAA,YACH,OAAO;AAAA,YACP,UAAU,EAAE,KAAK,iBAAiB,OAAO,MAAM;AAAA,YAC/C,gBAAgB;AAAA,YAChB,UAAU;AAAA,cACR,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,kBACE,WAAW,CAAC,eACV,sBAAS,MAAM,KAAK,OAAO,WAAW;AAAA,kBACxC,KAAK;AAAA,oBACH,IAAI;AAAA,oBACJ,YAAY;AAAA,oBACZ,UAAU,EAAE,KAAK,iBAAiB,OAAO,EAAE;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,WAAW;AAAA,UACT,KAAK;AAAA,YACH,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW;AAAA,cACT,aACE;AAAA,YACJ;AAAA,YACA,aAAa;AAAA,cACX,OAAO;AAAA,cACP,UAAU;AAAA,cACV,gBAAgB;AAAA,cAChB,UAAU,CAAC,EAAE,IAAI,UAAU,YAAY,QAAQ,UAAU,EAAE,CAAC;AAAA,YAC9D;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,IAAM,YAA8B;AAAA,EACzC,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,eAAe;AAAA,IAC1B,WAAW;AAAA,IACX,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,UACJ,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,aAAa;AAAA,UACX,KAAK;AAAA,YACH,OAAO;AAAA,YACP,UAAU,EAAE,OAAO,MAAM;AAAA,YACzB,UAAU;AAAA,cACR,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,kBACE,WAAW,CAAC,eACV,sBAAS,MAAM,KAAK,OAAO,WAAW;AAAA,kBACxC,KAAK;AAAA,oBACH,IAAI;AAAA,oBACJ,YAAY;AAAA,oBACZ,UAAU,EAAE,KAAK,iBAAiB,OAAO,EAAE;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW,CAAC;AAAA,YACZ,aAAa;AAAA,cACX,OAAO;AAAA,cACP,UAAU;AAAA,cACV,UAAU,CAAC,EAAE,IAAI,UAAU,YAAY,OAAO,UAAU,EAAE,CAAC;AAAA,YAC7D;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,IAAM,WAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,aAAa;AAAA,IACxB,WAAW;AAAA,IACX,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,EACT,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW,CAAC;AAAA,YACZ,aAAa,CAAC;AAAA,YACd,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,IAAM,OAAyB;AAAA,EACpC,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,eAAe;AAAA,IAC1B,WAAW;AAAA,IACX,MAAM,EAAE,MAAM,aAAa;AAAA,IAC3B,MAAM,EAAE,OAAO,mBAAmB;AAAA,IAClC,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,WAAW;AAAA,UACT,KAAK;AAAA,YACH,IAAI;AAAA,UACN;AAAA,QACF;AAAA,QACA,aAAa;AAAA,UACX,KAAK;AAAA,YACH,gBAAgB,EAAE,OAAO,aAAa;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW;AAAA;AAAA,cAET,IAAI;AAAA,YACN;AAAA,YACA,aAAa;AAAA,cACX,gBAAgB;AAAA,YAClB;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":["import_dev","import_dev","import_dev"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Long-lived Conversions API access token from Snapchat Ads Manager',\n ),\n pixelId: z.string().min(1).describe('Snap Pixel ID'),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Conversions API base URL (default https://tr.snapchat.com/v3/)',\n )\n .optional(),\n action_source: z\n .enum(['WEB', 'MOBILE_APP', 'OFFLINE'])\n .describe('Event action source (default WEB)')\n .optional(),\n doNotHash: z\n .array(z.string())\n .describe(\"User data fields to skip hashing (like ['em', 'ph'])\")\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\"Mapping for user data fields (like { em: 'user.email' })\")\n .optional(),\n testMode: z\n .boolean()\n .describe(\n 'When true, sends events to /events/validate instead of /events for testing',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Snapchat Conversions API Mapping Schema\n * Snapchat CAPI has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Snapchat Conversions API event names (UPPERCASE).\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nexport const StandardEventNameSchema = z.union([\n z.enum([\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 ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Snapchat Conversions API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: {\n status: 'OK',\n request_id: 'mock-123',\n },\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Snapchat Conversions API events without making\n * actual HTTP requests to Snapchat's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Snapchat Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is `${settings.url}${settings.pixelId}/${path}?access_token=${settings.accessToken}`\n * with `path` = `events` (or `events/validate` when `testMode` is set),\n * and `body` is the JSON-stringified `{ data: [snapchatEvent] }` payload.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = 'p1x3l1d'`,\n * so every endpoint resolves to:\n * https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t\n *\n * Body fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * 1. event_name\n * 2. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 3. action_source (default 'WEB')\n * 4. event_id\n * 5. user_data (hashed per Snapchat's PII requirements)\n * 6. custom_data (mapped event data, excluding user_data/custom_data keys)\n * 7. event_source_url (appended last when action_source === 'WEB')\n */\nconst ENDPOINT =\n 'https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.',\n in: getEvent('order complete', {\n id: 'e1f2a3b4c5d60001',\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/checkout/complete',\n },\n }),\n mapping: {\n name: 'PURCHASE',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.total',\n currency: { key: 'data.currency', value: 'EUR' },\n transaction_id: 'data.id',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n user_data: {\n map: {\n external_id: 'user.id',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'PURCHASE',\n event_time: 1700000900,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60001',\n user_data: {\n external_id:\n 'fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8',\n },\n custom_data: {\n value: 249.99,\n currency: 'EUR',\n transaction_id: 'ORD-300',\n contents: [{ id: 'SKU-A1', item_price: 124.99, quantity: 2 }],\n },\n event_source_url: 'https://shop.example.com/checkout/complete',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add is sent to Snapchat as an ADD_CART conversion with value and product details.',\n in: getEvent('product add', {\n id: 'e1f2a3b4c5d60002',\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n color: 'blue',\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/running-shoes',\n },\n }),\n mapping: {\n name: 'ADD_CART',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.price',\n currency: { value: 'EUR' },\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'ADD_CART',\n event_time: 1700000901,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60002',\n user_data: {},\n custom_data: {\n value: 89.99,\n currency: 'EUR',\n contents: [{ id: 'SKU-B2', item_price: 89.99, quantity: 1 }],\n },\n event_source_url: 'https://shop.example.com/products/running-shoes',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is forwarded to Snapchat with the event source URL and no extra custom data.',\n in: getEvent('page view', {\n id: 'e1f2a3b4c5d60003',\n timestamp: 1700000902000,\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/docs/',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'page view',\n event_time: 1700000902,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60003',\n user_data: {},\n custom_data: {},\n event_source_url: 'https://example.com/docs/',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Sign up',\n description:\n 'A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.',\n in: getEvent('form submit', {\n id: 'e1f2a3b4c5d60004',\n timestamp: 1700000903000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/contact',\n },\n }),\n mapping: {\n name: 'SIGN_UP',\n data: {\n map: {\n user_data: {\n map: {\n em: 'user.email',\n },\n },\n custom_data: {\n map: {\n sign_up_method: { value: 'newsletter' },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'SIGN_UP',\n event_time: 1700000903,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60004',\n user_data: {\n // sha256('user@example.com')\n em: 'b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514',\n },\n custom_data: {\n sign_up_method: 'newsletter',\n },\n event_source_url: 'https://example.com/contact',\n },\n ],\n }),\n ],\n ],\n};\n"],"mappings":"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","names":["import_dev","import_dev","import_dev"]}
|
package/dist/dev.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,t=(t,a)=>{for(var r in a)e(t,r,{get:a[r],enumerable:!0})},a={};t(a,{MappingSchema:()=>o,SettingsSchema:()=>
|
|
1
|
+
var e=Object.defineProperty,t=(t,a)=>{for(var r in a)e(t,r,{get:a[r],enumerable:!0})},a={};t(a,{MappingSchema:()=>o,SettingsSchema:()=>s,StandardEventNameSchema:()=>d,mapping:()=>m,settings:()=>p});import{zodToSchema as r}from"@walkeros/core/dev";import{z as n}from"@walkeros/core/dev";var s=n.object({accessToken:n.string().min(1).describe("Long-lived Conversions API access token from Snapchat Ads Manager"),pixelId:n.string().min(1).describe("Snap Pixel ID"),url:n.string().url().describe("Custom Conversions API base URL (default https://tr.snapchat.com/v3/)").optional(),action_source:n.enum(["WEB","MOBILE_APP","OFFLINE"]).describe("Event action source (default WEB)").optional(),doNotHash:n.array(n.string()).describe("User data fields to skip hashing (like ['em', 'ph'])").optional(),user_data:n.record(n.string(),n.string()).describe("Mapping for user data fields (like { em: 'user.email' })").optional(),testMode:n.boolean().describe("When true, sends events to /events/validate instead of /events for testing").optional()});import{z as i}from"@walkeros/core/dev";var o=i.object({});import{z as c}from"@walkeros/core/dev";var d=c.union([c.enum(["PAGE_VIEW","VIEW_CONTENT","ADD_CART","ADD_TO_WISHLIST","START_CHECKOUT","ADD_BILLING","PURCHASE","SIGN_UP","SEARCH","SAVE","SUBSCRIBE","COMPLETE_TUTORIAL","START_TRIAL","AD_CLICK","AD_VIEW","APP_OPEN","LEVEL_COMPLETE","INVITE","LOGIN","SHARE","RESERVE","ACHIEVEMENT_UNLOCKED","SPENT_CREDITS","RATE","LIST_VIEW","CUSTOM_EVENT_1","CUSTOM_EVENT_2","CUSTOM_EVENT_3","CUSTOM_EVENT_4","CUSTOM_EVENT_5"]),c.string()]),p=r(s),m=r(o),u={};t(u,{env:()=>_,step:()=>E});var _={};t(_,{push:()=>l,simulation:()=>v});var l={sendServer:async()=>({ok:!0,data:{status:"OK",request_id:"mock-123"}})},v=["sendServer"],E={};t(E,{addToCart:()=>A,lead:()=>T,pageView:()=>g,purchase:()=>b});import{getEvent as S,isObject as h}from"@walkeros/core";var f="https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t",b={title:"Purchase",description:"A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.",in:S("order complete",{id:"e1f2a3b4c5d60001",timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",name:"Widget Pro",price:124.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com/checkout/complete"}}),mapping:{name:"PURCHASE",data:{map:{custom_data:{map:{value:"data.total",currency:{key:"data.currency",value:"EUR"},transaction_id:"data.id",contents:{loop:["nested",{condition:e=>h(e)&&"product"===e.entity,map:{id:"data.id",item_price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}},user_data:{map:{external_id:"user.id"}}}}},out:[["sendServer",f,JSON.stringify({data:[{event_name:"PURCHASE",event_time:1700000900,action_source:"WEB",event_id:"e1f2a3b4c5d60001",user_data:{external_id:"fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8"},custom_data:{value:249.99,currency:"EUR",transaction_id:"ORD-300",contents:[{id:"SKU-A1",item_price:124.99,quantity:2}]},event_source_url:"https://shop.example.com/checkout/complete"}]})]]},A={title:"Add to cart",description:"A product add is sent to Snapchat as an ADD_CART conversion with value and product details.",in:S("product add",{id:"e1f2a3b4c5d60002",timestamp:1700000901e3,data:{id:"SKU-B2",name:"Running Shoes",price:89.99,color:"blue"},nested:[{entity:"product",data:{id:"SKU-B2",name:"Running Shoes",price:89.99,quantity:1}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/running-shoes"}}),mapping:{name:"ADD_CART",data:{map:{custom_data:{map:{value:"data.price",currency:{value:"EUR"},contents:{loop:["nested",{condition:e=>h(e)&&"product"===e.entity,map:{id:"data.id",item_price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}}}},out:[["sendServer",f,JSON.stringify({data:[{event_name:"ADD_CART",event_time:1700000901,action_source:"WEB",event_id:"e1f2a3b4c5d60002",user_data:{},custom_data:{value:89.99,currency:"EUR",contents:[{id:"SKU-B2",item_price:89.99,quantity:1}]},event_source_url:"https://shop.example.com/products/running-shoes"}]})]]},g={title:"Page view",description:"A page view is forwarded to Snapchat with the event source URL and no extra custom data.",in:S("page view",{id:"e1f2a3b4c5d60003",timestamp:1700000902e3,source:{type:"browser",platform:"web",url:"https://example.com/docs/"}}),mapping:void 0,out:[["sendServer",f,JSON.stringify({data:[{event_name:"page view",event_time:1700000902,action_source:"WEB",event_id:"e1f2a3b4c5d60003",user_data:{},custom_data:{},event_source_url:"https://example.com/docs/"}]})]]},T={title:"Sign up",description:"A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.",in:S("form submit",{id:"e1f2a3b4c5d60004",timestamp:1700000903e3,data:{type:"newsletter"},user:{email:"user@example.com"},source:{type:"browser",platform:"web",url:"https://example.com/contact"}}),mapping:{name:"SIGN_UP",data:{map:{user_data:{map:{em:"user.email"}},custom_data:{map:{sign_up_method:{value:"newsletter"}}}}}},out:[["sendServer",f,JSON.stringify({data:[{event_name:"SIGN_UP",event_time:1700000903,action_source:"WEB",event_id:"e1f2a3b4c5d60004",user_data:{em:"b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514"},custom_data:{sign_up_method:"newsletter"},event_source_url:"https://example.com/contact"}]})]]};export{u as examples,a as schemas};//# sourceMappingURL=dev.mjs.map
|
package/dist/dev.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Long-lived Conversions API access token from Snapchat Ads Manager',\n ),\n pixelId: z.string().min(1).describe('Snap Pixel ID'),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Conversions API base URL (default https://tr.snapchat.com/v3/)',\n )\n .optional(),\n action_source: z\n .enum(['WEB', 'MOBILE_APP', 'OFFLINE'])\n .describe('Event action source (default WEB)')\n .optional(),\n doNotHash: z\n .array(z.string())\n .describe(\"User data fields to skip hashing (like ['em', 'ph'])\")\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\"Mapping for user data fields (like { em: 'user.email' })\")\n .optional(),\n testMode: z\n .boolean()\n .describe(\n 'When true, sends events to /events/validate instead of /events for testing',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Snapchat Conversions API Mapping Schema\n * Snapchat CAPI has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Snapchat Conversions API event names (UPPERCASE).\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nexport const StandardEventNameSchema = z.union([\n z.enum([\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 ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Snapchat Conversions API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: {\n status: 'OK',\n request_id: 'mock-123',\n },\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Snapchat Conversions API events without making\n * actual HTTP requests to Snapchat's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Snapchat Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is `${settings.url}${settings.pixelId}/${path}?access_token=${settings.accessToken}`\n * with `path` = `events` (or `events/validate` when `testMode` is set),\n * and `body` is the JSON-stringified `{ data: [snapchatEvent] }` payload.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = 'p1x3l1d'`,\n * so every endpoint resolves to:\n * https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t\n *\n * Body fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * 1. event_name\n * 2. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 3. action_source (default 'WEB')\n * 4. event_id\n * 5. user_data (hashed per Snapchat's PII requirements)\n * 6. custom_data (mapped event data, excluding user_data/custom_data keys)\n * 7. event_source_url (appended last when action_source === 'WEB')\n */\nconst ENDPOINT =\n 'https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.',\n in: getEvent('order complete', {\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'server',\n id: 'https://shop.example.com/checkout/complete',\n previous_id: '',\n },\n }),\n mapping: {\n name: 'PURCHASE',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.total',\n currency: { key: 'data.currency', value: 'EUR' },\n transaction_id: 'data.id',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n user_data: {\n map: {\n external_id: 'user.id',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'PURCHASE',\n event_time: 1700000900,\n action_source: 'WEB',\n event_id: '1700000900000-gr0up-1',\n user_data: {\n external_id:\n 'fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8',\n },\n custom_data: {\n value: 249.99,\n currency: 'EUR',\n transaction_id: 'ORD-300',\n contents: [{ id: 'SKU-A1', item_price: 124.99, quantity: 2 }],\n },\n event_source_url: 'https://shop.example.com/checkout/complete',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add is sent to Snapchat as an ADD_CART conversion with value and product details.',\n in: getEvent('product add', {\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n color: 'blue',\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'server',\n id: 'https://shop.example.com/products/running-shoes',\n previous_id: '',\n },\n }),\n mapping: {\n name: 'ADD_CART',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.price',\n currency: { value: 'EUR' },\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'ADD_CART',\n event_time: 1700000901,\n action_source: 'WEB',\n event_id: '1700000901000-gr0up-1',\n user_data: {},\n custom_data: {\n value: 89.99,\n currency: 'EUR',\n contents: [{ id: 'SKU-B2', item_price: 89.99, quantity: 1 }],\n },\n event_source_url: 'https://shop.example.com/products/running-shoes',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is forwarded to Snapchat with the event source URL and no extra custom data.',\n in: getEvent('page view', {\n timestamp: 1700000902000,\n source: {\n type: 'server',\n id: 'https://example.com/docs/',\n previous_id: '',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'page view',\n event_time: 1700000902,\n action_source: 'WEB',\n event_id: '1700000902000-gr0up-1',\n user_data: {},\n custom_data: {},\n event_source_url: 'https://example.com/docs/',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Sign up',\n description:\n 'A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.',\n in: getEvent('form submit', {\n timestamp: 1700000903000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'server',\n id: 'https://example.com/contact',\n previous_id: '',\n },\n }),\n mapping: {\n name: 'SIGN_UP',\n data: {\n map: {\n user_data: {\n map: {\n em: 'user.email',\n },\n },\n custom_data: {\n map: {\n sign_up_method: { value: 'newsletter' },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'SIGN_UP',\n event_time: 1700000903,\n action_source: 'WEB',\n event_id: '1700000903000-gr0up-1',\n user_data: {\n // sha256('user@example.com')\n em: 'b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514',\n },\n custom_data: {\n sign_up_method: 'newsletter',\n },\n event_source_url: 'https://example.com/contact',\n },\n ],\n }),\n ],\n ],\n};\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,SAAS;AAEX,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,aAAa,EACV,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,eAAe;AAAA,EACnD,KAAK,EACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAe,EACZ,KAAK,CAAC,OAAO,cAAc,SAAS,CAAC,EACrC,SAAS,mCAAmC,EAC5C,SAAS;AAAA,EACZ,WAAW,EACR,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,sDAAsD,EAC/D,SAAS;AAAA,EACZ,WAAW,EACR,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAC7B,SAAS,0DAA0D,EACnE,SAAS;AAAA,EACZ,UAAU,EACP,QAAQ,EACR;AAAA,IACC;AAAA,EACF,EACC,SAAS;AACd,CAAC;;;ACnCD,SAAS,KAAAA,UAAS;AAMX,IAAM,gBAAgBA,GAAE,OAAO,CAAC,CAAC;;;ACNxC,SAAS,KAAAC,UAAS;AAMX,IAAM,0BAA0BA,GAAE,MAAM;AAAA,EAC7CA,GAAE,KAAK;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA,EACDA,GAAE,OAAO;AAAA;AACX,CAAC;;;AH9BM,IAAM,WAAW,YAAY,cAAc;AAC3C,IAAM,UAAU,YAAY,aAAa;;;AIXhD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAiBA,IAAM,iBAAiC,aAAa;AAAA,EAClD,IAAI;AAAA,EACJ,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAQO,IAAM,OAAY;AAAA,EACvB,YAAY;AACd;AAEO,IAAM,aAAa,CAAC,YAAY;;;ACnCvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,SAAS,UAAU,gBAAgB;AAwBnC,IAAM,WACJ;AAEK,IAAM,WAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,kBAAkB;AAAA,IAC7B,WAAW;AAAA,IACX,MAAM,EAAE,IAAI,WAAW,OAAO,QAAQ,UAAU,MAAM;AAAA,IACtD,QAAQ;AAAA,MACN;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,EAAE,IAAI,UAAU,MAAM,cAAc,OAAO,QAAQ,UAAU,EAAE;AAAA,MACvE;AAAA,IACF;AAAA,IACA,MAAM,EAAE,IAAI,YAAY,QAAQ,aAAa;AAAA,IAC7C,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,aAAa;AAAA,UACX,KAAK;AAAA,YACH,OAAO;AAAA,YACP,UAAU,EAAE,KAAK,iBAAiB,OAAO,MAAM;AAAA,YAC/C,gBAAgB;AAAA,YAChB,UAAU;AAAA,cACR,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,kBACE,WAAW,CAAC,WACV,SAAS,MAAM,KAAK,OAAO,WAAW;AAAA,kBACxC,KAAK;AAAA,oBACH,IAAI;AAAA,oBACJ,YAAY;AAAA,oBACZ,UAAU,EAAE,KAAK,iBAAiB,OAAO,EAAE;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,WAAW;AAAA,UACT,KAAK;AAAA,YACH,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW;AAAA,cACT,aACE;AAAA,YACJ;AAAA,YACA,aAAa;AAAA,cACX,OAAO;AAAA,cACP,UAAU;AAAA,cACV,gBAAgB;AAAA,cAChB,UAAU,CAAC,EAAE,IAAI,UAAU,YAAY,QAAQ,UAAU,EAAE,CAAC;AAAA,YAC9D;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,IAAM,YAA8B;AAAA,EACzC,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,eAAe;AAAA,IAC1B,WAAW;AAAA,IACX,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,UACJ,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,aAAa;AAAA,UACX,KAAK;AAAA,YACH,OAAO;AAAA,YACP,UAAU,EAAE,OAAO,MAAM;AAAA,YACzB,UAAU;AAAA,cACR,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,kBACE,WAAW,CAAC,WACV,SAAS,MAAM,KAAK,OAAO,WAAW;AAAA,kBACxC,KAAK;AAAA,oBACH,IAAI;AAAA,oBACJ,YAAY;AAAA,oBACZ,UAAU,EAAE,KAAK,iBAAiB,OAAO,EAAE;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW,CAAC;AAAA,YACZ,aAAa;AAAA,cACX,OAAO;AAAA,cACP,UAAU;AAAA,cACV,UAAU,CAAC,EAAE,IAAI,UAAU,YAAY,OAAO,UAAU,EAAE,CAAC;AAAA,YAC7D;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,IAAM,WAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,aAAa;AAAA,IACxB,WAAW;AAAA,IACX,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,EACT,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW,CAAC;AAAA,YACZ,aAAa,CAAC;AAAA,YACd,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,IAAM,OAAyB;AAAA,EACpC,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,eAAe;AAAA,IAC1B,WAAW;AAAA,IACX,MAAM,EAAE,MAAM,aAAa;AAAA,IAC3B,MAAM,EAAE,OAAO,mBAAmB;AAAA,IAClC,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,WAAW;AAAA,UACT,KAAK;AAAA,YACH,IAAI;AAAA,UACN;AAAA,QACF;AAAA,QACA,aAAa;AAAA,UACX,KAAK;AAAA,YACH,gBAAgB,EAAE,OAAO,aAAa;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,UACJ;AAAA,YACE,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,UAAU;AAAA,YACV,WAAW;AAAA;AAAA,cAET,IAAI;AAAA,YACN;AAAA,YACA,aAAa;AAAA,cACX,gBAAgB;AAAA,YAClB;AAAA,YACA,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":["z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Long-lived Conversions API access token from Snapchat Ads Manager',\n ),\n pixelId: z.string().min(1).describe('Snap Pixel ID'),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Conversions API base URL (default https://tr.snapchat.com/v3/)',\n )\n .optional(),\n action_source: z\n .enum(['WEB', 'MOBILE_APP', 'OFFLINE'])\n .describe('Event action source (default WEB)')\n .optional(),\n doNotHash: z\n .array(z.string())\n .describe(\"User data fields to skip hashing (like ['em', 'ph'])\")\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\"Mapping for user data fields (like { em: 'user.email' })\")\n .optional(),\n testMode: z\n .boolean()\n .describe(\n 'When true, sends events to /events/validate instead of /events for testing',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Snapchat Conversions API Mapping Schema\n * Snapchat CAPI has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Snapchat Conversions API event names (UPPERCASE).\n * https://businesshelp.snapchat.com/s/article/capi-parameters\n */\nexport const StandardEventNameSchema = z.union([\n z.enum([\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 ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Snapchat Conversions API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: {\n status: 'OK',\n request_id: 'mock-123',\n },\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Snapchat Conversions API events without making\n * actual HTTP requests to Snapchat's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Snapchat Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is `${settings.url}${settings.pixelId}/${path}?access_token=${settings.accessToken}`\n * with `path` = `events` (or `events/validate` when `testMode` is set),\n * and `body` is the JSON-stringified `{ data: [snapchatEvent] }` payload.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = 'p1x3l1d'`,\n * so every endpoint resolves to:\n * https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t\n *\n * Body fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * 1. event_name\n * 2. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 3. action_source (default 'WEB')\n * 4. event_id\n * 5. user_data (hashed per Snapchat's PII requirements)\n * 6. custom_data (mapped event data, excluding user_data/custom_data keys)\n * 7. event_source_url (appended last when action_source === 'WEB')\n */\nconst ENDPOINT =\n 'https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.',\n in: getEvent('order complete', {\n id: 'e1f2a3b4c5d60001',\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/checkout/complete',\n },\n }),\n mapping: {\n name: 'PURCHASE',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.total',\n currency: { key: 'data.currency', value: 'EUR' },\n transaction_id: 'data.id',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n user_data: {\n map: {\n external_id: 'user.id',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'PURCHASE',\n event_time: 1700000900,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60001',\n user_data: {\n external_id:\n 'fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8',\n },\n custom_data: {\n value: 249.99,\n currency: 'EUR',\n transaction_id: 'ORD-300',\n contents: [{ id: 'SKU-A1', item_price: 124.99, quantity: 2 }],\n },\n event_source_url: 'https://shop.example.com/checkout/complete',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add is sent to Snapchat as an ADD_CART conversion with value and product details.',\n in: getEvent('product add', {\n id: 'e1f2a3b4c5d60002',\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n color: 'blue',\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/running-shoes',\n },\n }),\n mapping: {\n name: 'ADD_CART',\n data: {\n map: {\n custom_data: {\n map: {\n value: 'data.price',\n currency: { value: 'EUR' },\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'ADD_CART',\n event_time: 1700000901,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60002',\n user_data: {},\n custom_data: {\n value: 89.99,\n currency: 'EUR',\n contents: [{ id: 'SKU-B2', item_price: 89.99, quantity: 1 }],\n },\n event_source_url: 'https://shop.example.com/products/running-shoes',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is forwarded to Snapchat with the event source URL and no extra custom data.',\n in: getEvent('page view', {\n id: 'e1f2a3b4c5d60003',\n timestamp: 1700000902000,\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/docs/',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'page view',\n event_time: 1700000902,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60003',\n user_data: {},\n custom_data: {},\n event_source_url: 'https://example.com/docs/',\n },\n ],\n }),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Sign up',\n description:\n 'A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.',\n in: getEvent('form submit', {\n id: 'e1f2a3b4c5d60004',\n timestamp: 1700000903000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/contact',\n },\n }),\n mapping: {\n name: 'SIGN_UP',\n data: {\n map: {\n user_data: {\n map: {\n em: 'user.email',\n },\n },\n custom_data: {\n map: {\n sign_up_method: { value: 'newsletter' },\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'SIGN_UP',\n event_time: 1700000903,\n action_source: 'WEB',\n event_id: 'e1f2a3b4c5d60004',\n user_data: {\n // sha256('user@example.com')\n em: 'b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514',\n },\n custom_data: {\n sign_up_method: 'newsletter',\n },\n event_source_url: 'https://example.com/contact',\n },\n ],\n }),\n ],\n ],\n};\n"],"mappings":"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","names":["z","z"]}
|
package/dist/examples/index.js
CHANGED
|
@@ -57,6 +57,7 @@ var purchase = {
|
|
|
57
57
|
title: "Purchase",
|
|
58
58
|
description: "A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.",
|
|
59
59
|
in: (0, import_core.getEvent)("order complete", {
|
|
60
|
+
id: "e1f2a3b4c5d60001",
|
|
60
61
|
timestamp: 17000009e5,
|
|
61
62
|
data: { id: "ORD-300", total: 249.99, currency: "EUR" },
|
|
62
63
|
nested: [
|
|
@@ -67,9 +68,9 @@ var purchase = {
|
|
|
67
68
|
],
|
|
68
69
|
user: { id: "user-123", device: "device-456" },
|
|
69
70
|
source: {
|
|
70
|
-
type: "
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
type: "browser",
|
|
72
|
+
platform: "web",
|
|
73
|
+
url: "https://shop.example.com/checkout/complete"
|
|
73
74
|
}
|
|
74
75
|
}),
|
|
75
76
|
mapping: {
|
|
@@ -114,7 +115,7 @@ var purchase = {
|
|
|
114
115
|
event_name: "PURCHASE",
|
|
115
116
|
event_time: 1700000900,
|
|
116
117
|
action_source: "WEB",
|
|
117
|
-
event_id: "
|
|
118
|
+
event_id: "e1f2a3b4c5d60001",
|
|
118
119
|
user_data: {
|
|
119
120
|
external_id: "fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8"
|
|
120
121
|
},
|
|
@@ -135,6 +136,7 @@ var addToCart = {
|
|
|
135
136
|
title: "Add to cart",
|
|
136
137
|
description: "A product add is sent to Snapchat as an ADD_CART conversion with value and product details.",
|
|
137
138
|
in: (0, import_core.getEvent)("product add", {
|
|
139
|
+
id: "e1f2a3b4c5d60002",
|
|
138
140
|
timestamp: 1700000901e3,
|
|
139
141
|
data: {
|
|
140
142
|
id: "SKU-B2",
|
|
@@ -154,9 +156,9 @@ var addToCart = {
|
|
|
154
156
|
}
|
|
155
157
|
],
|
|
156
158
|
source: {
|
|
157
|
-
type: "
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
type: "browser",
|
|
160
|
+
platform: "web",
|
|
161
|
+
url: "https://shop.example.com/products/running-shoes"
|
|
160
162
|
}
|
|
161
163
|
}),
|
|
162
164
|
mapping: {
|
|
@@ -195,7 +197,7 @@ var addToCart = {
|
|
|
195
197
|
event_name: "ADD_CART",
|
|
196
198
|
event_time: 1700000901,
|
|
197
199
|
action_source: "WEB",
|
|
198
|
-
event_id: "
|
|
200
|
+
event_id: "e1f2a3b4c5d60002",
|
|
199
201
|
user_data: {},
|
|
200
202
|
custom_data: {
|
|
201
203
|
value: 89.99,
|
|
@@ -213,11 +215,12 @@ var pageView = {
|
|
|
213
215
|
title: "Page view",
|
|
214
216
|
description: "A page view is forwarded to Snapchat with the event source URL and no extra custom data.",
|
|
215
217
|
in: (0, import_core.getEvent)("page view", {
|
|
218
|
+
id: "e1f2a3b4c5d60003",
|
|
216
219
|
timestamp: 1700000902e3,
|
|
217
220
|
source: {
|
|
218
|
-
type: "
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
type: "browser",
|
|
222
|
+
platform: "web",
|
|
223
|
+
url: "https://example.com/docs/"
|
|
221
224
|
}
|
|
222
225
|
}),
|
|
223
226
|
mapping: void 0,
|
|
@@ -231,7 +234,7 @@ var pageView = {
|
|
|
231
234
|
event_name: "page view",
|
|
232
235
|
event_time: 1700000902,
|
|
233
236
|
action_source: "WEB",
|
|
234
|
-
event_id: "
|
|
237
|
+
event_id: "e1f2a3b4c5d60003",
|
|
235
238
|
user_data: {},
|
|
236
239
|
custom_data: {},
|
|
237
240
|
event_source_url: "https://example.com/docs/"
|
|
@@ -245,13 +248,14 @@ var lead = {
|
|
|
245
248
|
title: "Sign up",
|
|
246
249
|
description: "A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.",
|
|
247
250
|
in: (0, import_core.getEvent)("form submit", {
|
|
251
|
+
id: "e1f2a3b4c5d60004",
|
|
248
252
|
timestamp: 1700000903e3,
|
|
249
253
|
data: { type: "newsletter" },
|
|
250
254
|
user: { email: "user@example.com" },
|
|
251
255
|
source: {
|
|
252
|
-
type: "
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
type: "browser",
|
|
257
|
+
platform: "web",
|
|
258
|
+
url: "https://example.com/contact"
|
|
255
259
|
}
|
|
256
260
|
}),
|
|
257
261
|
mapping: {
|
|
@@ -281,7 +285,7 @@ var lead = {
|
|
|
281
285
|
event_name: "SIGN_UP",
|
|
282
286
|
event_time: 1700000903,
|
|
283
287
|
action_source: "WEB",
|
|
284
|
-
event_id: "
|
|
288
|
+
event_id: "e1f2a3b4c5d60004",
|
|
285
289
|
user_data: {
|
|
286
290
|
// sha256('user@example.com')
|
|
287
291
|
em: "b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514"
|
package/dist/examples/index.mjs
CHANGED
|
@@ -36,6 +36,7 @@ var purchase = {
|
|
|
36
36
|
title: "Purchase",
|
|
37
37
|
description: "A completed order is sent to the Snapchat Conversions API as a PURCHASE with value, currency, and contents.",
|
|
38
38
|
in: getEvent("order complete", {
|
|
39
|
+
id: "e1f2a3b4c5d60001",
|
|
39
40
|
timestamp: 17000009e5,
|
|
40
41
|
data: { id: "ORD-300", total: 249.99, currency: "EUR" },
|
|
41
42
|
nested: [
|
|
@@ -46,9 +47,9 @@ var purchase = {
|
|
|
46
47
|
],
|
|
47
48
|
user: { id: "user-123", device: "device-456" },
|
|
48
49
|
source: {
|
|
49
|
-
type: "
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
type: "browser",
|
|
51
|
+
platform: "web",
|
|
52
|
+
url: "https://shop.example.com/checkout/complete"
|
|
52
53
|
}
|
|
53
54
|
}),
|
|
54
55
|
mapping: {
|
|
@@ -93,7 +94,7 @@ var purchase = {
|
|
|
93
94
|
event_name: "PURCHASE",
|
|
94
95
|
event_time: 1700000900,
|
|
95
96
|
action_source: "WEB",
|
|
96
|
-
event_id: "
|
|
97
|
+
event_id: "e1f2a3b4c5d60001",
|
|
97
98
|
user_data: {
|
|
98
99
|
external_id: "fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8"
|
|
99
100
|
},
|
|
@@ -114,6 +115,7 @@ var addToCart = {
|
|
|
114
115
|
title: "Add to cart",
|
|
115
116
|
description: "A product add is sent to Snapchat as an ADD_CART conversion with value and product details.",
|
|
116
117
|
in: getEvent("product add", {
|
|
118
|
+
id: "e1f2a3b4c5d60002",
|
|
117
119
|
timestamp: 1700000901e3,
|
|
118
120
|
data: {
|
|
119
121
|
id: "SKU-B2",
|
|
@@ -133,9 +135,9 @@ var addToCart = {
|
|
|
133
135
|
}
|
|
134
136
|
],
|
|
135
137
|
source: {
|
|
136
|
-
type: "
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
type: "browser",
|
|
139
|
+
platform: "web",
|
|
140
|
+
url: "https://shop.example.com/products/running-shoes"
|
|
139
141
|
}
|
|
140
142
|
}),
|
|
141
143
|
mapping: {
|
|
@@ -174,7 +176,7 @@ var addToCart = {
|
|
|
174
176
|
event_name: "ADD_CART",
|
|
175
177
|
event_time: 1700000901,
|
|
176
178
|
action_source: "WEB",
|
|
177
|
-
event_id: "
|
|
179
|
+
event_id: "e1f2a3b4c5d60002",
|
|
178
180
|
user_data: {},
|
|
179
181
|
custom_data: {
|
|
180
182
|
value: 89.99,
|
|
@@ -192,11 +194,12 @@ var pageView = {
|
|
|
192
194
|
title: "Page view",
|
|
193
195
|
description: "A page view is forwarded to Snapchat with the event source URL and no extra custom data.",
|
|
194
196
|
in: getEvent("page view", {
|
|
197
|
+
id: "e1f2a3b4c5d60003",
|
|
195
198
|
timestamp: 1700000902e3,
|
|
196
199
|
source: {
|
|
197
|
-
type: "
|
|
198
|
-
|
|
199
|
-
|
|
200
|
+
type: "browser",
|
|
201
|
+
platform: "web",
|
|
202
|
+
url: "https://example.com/docs/"
|
|
200
203
|
}
|
|
201
204
|
}),
|
|
202
205
|
mapping: void 0,
|
|
@@ -210,7 +213,7 @@ var pageView = {
|
|
|
210
213
|
event_name: "page view",
|
|
211
214
|
event_time: 1700000902,
|
|
212
215
|
action_source: "WEB",
|
|
213
|
-
event_id: "
|
|
216
|
+
event_id: "e1f2a3b4c5d60003",
|
|
214
217
|
user_data: {},
|
|
215
218
|
custom_data: {},
|
|
216
219
|
event_source_url: "https://example.com/docs/"
|
|
@@ -224,13 +227,14 @@ var lead = {
|
|
|
224
227
|
title: "Sign up",
|
|
225
228
|
description: "A newsletter form submission is sent to Snapchat as a SIGN_UP conversion with a hashed email.",
|
|
226
229
|
in: getEvent("form submit", {
|
|
230
|
+
id: "e1f2a3b4c5d60004",
|
|
227
231
|
timestamp: 1700000903e3,
|
|
228
232
|
data: { type: "newsletter" },
|
|
229
233
|
user: { email: "user@example.com" },
|
|
230
234
|
source: {
|
|
231
|
-
type: "
|
|
232
|
-
|
|
233
|
-
|
|
235
|
+
type: "browser",
|
|
236
|
+
platform: "web",
|
|
237
|
+
url: "https://example.com/contact"
|
|
234
238
|
}
|
|
235
239
|
}),
|
|
236
240
|
mapping: {
|
|
@@ -260,7 +264,7 @@ var lead = {
|
|
|
260
264
|
event_name: "SIGN_UP",
|
|
261
265
|
event_time: 1700000903,
|
|
262
266
|
action_source: "WEB",
|
|
263
|
-
event_id: "
|
|
267
|
+
event_id: "e1f2a3b4c5d60004",
|
|
264
268
|
user_data: {
|
|
265
269
|
// sha256('user@example.com')
|
|
266
270
|
em: "b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514"
|
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}){
|
|
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
|
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?.id) {\n snapchatEvent.event_source_url = event.source.id;\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"]}
|
|
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":"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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}){
|
|
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
|
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?.id) {\n snapchatEvent.event_source_url = event.source.id;\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)\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":[]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/server-destination-snapchat",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0-next-1777463920154",
|
|
5
5
|
"type": "destination",
|
|
6
6
|
"platform": [
|
|
7
7
|
"server"
|
|
@@ -127,22 +127,16 @@
|
|
|
127
127
|
"consent": {
|
|
128
128
|
"functional": true
|
|
129
129
|
},
|
|
130
|
-
"id": "
|
|
130
|
+
"id": "e1f2a3b4c5d60002",
|
|
131
131
|
"trigger": "click",
|
|
132
132
|
"entity": "product",
|
|
133
133
|
"action": "add",
|
|
134
134
|
"timestamp": 1700000901000,
|
|
135
135
|
"timing": 3.14,
|
|
136
|
-
"group": "gr0up",
|
|
137
|
-
"count": 1,
|
|
138
|
-
"version": {
|
|
139
|
-
"source": "3.4.2",
|
|
140
|
-
"tagging": 1
|
|
141
|
-
},
|
|
142
136
|
"source": {
|
|
143
|
-
"type": "
|
|
144
|
-
"
|
|
145
|
-
"
|
|
137
|
+
"type": "browser",
|
|
138
|
+
"platform": "web",
|
|
139
|
+
"url": "https://shop.example.com/products/running-shoes"
|
|
146
140
|
}
|
|
147
141
|
},
|
|
148
142
|
"mapping": {
|
|
@@ -182,7 +176,7 @@
|
|
|
182
176
|
[
|
|
183
177
|
"sendServer",
|
|
184
178
|
"https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t",
|
|
185
|
-
"{\"data\":[{\"event_name\":\"ADD_CART\",\"event_time\":1700000901,\"action_source\":\"WEB\",\"event_id\":\"
|
|
179
|
+
"{\"data\":[{\"event_name\":\"ADD_CART\",\"event_time\":1700000901,\"action_source\":\"WEB\",\"event_id\":\"e1f2a3b4c5d60002\",\"user_data\":{},\"custom_data\":{\"value\":89.99,\"currency\":\"EUR\",\"contents\":[{\"id\":\"SKU-B2\",\"item_price\":89.99,\"quantity\":1}]},\"event_source_url\":\"https://shop.example.com/products/running-shoes\"}]}"
|
|
186
180
|
]
|
|
187
181
|
]
|
|
188
182
|
},
|
|
@@ -214,35 +208,22 @@
|
|
|
214
208
|
"entity": "child",
|
|
215
209
|
"data": {
|
|
216
210
|
"is": "subordinated"
|
|
217
|
-
},
|
|
218
|
-
"nested": [],
|
|
219
|
-
"context": {
|
|
220
|
-
"element": [
|
|
221
|
-
"child",
|
|
222
|
-
0
|
|
223
|
-
]
|
|
224
211
|
}
|
|
225
212
|
}
|
|
226
213
|
],
|
|
227
214
|
"consent": {
|
|
228
215
|
"functional": true
|
|
229
216
|
},
|
|
230
|
-
"id": "
|
|
217
|
+
"id": "e1f2a3b4c5d60004",
|
|
231
218
|
"trigger": "test",
|
|
232
219
|
"entity": "form",
|
|
233
220
|
"action": "submit",
|
|
234
221
|
"timestamp": 1700000903000,
|
|
235
222
|
"timing": 3.14,
|
|
236
|
-
"group": "gr0up",
|
|
237
|
-
"count": 1,
|
|
238
|
-
"version": {
|
|
239
|
-
"source": "3.4.2",
|
|
240
|
-
"tagging": 1
|
|
241
|
-
},
|
|
242
223
|
"source": {
|
|
243
|
-
"type": "
|
|
244
|
-
"
|
|
245
|
-
"
|
|
224
|
+
"type": "browser",
|
|
225
|
+
"platform": "web",
|
|
226
|
+
"url": "https://example.com/contact"
|
|
246
227
|
}
|
|
247
228
|
},
|
|
248
229
|
"mapping": {
|
|
@@ -268,7 +249,7 @@
|
|
|
268
249
|
[
|
|
269
250
|
"sendServer",
|
|
270
251
|
"https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t",
|
|
271
|
-
"{\"data\":[{\"event_name\":\"SIGN_UP\",\"event_time\":1700000903,\"action_source\":\"WEB\",\"event_id\":\"
|
|
252
|
+
"{\"data\":[{\"event_name\":\"SIGN_UP\",\"event_time\":1700000903,\"action_source\":\"WEB\",\"event_id\":\"e1f2a3b4c5d60004\",\"user_data\":{\"em\":\"b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514\"},\"custom_data\":{\"sign_up_method\":\"newsletter\"},\"event_source_url\":\"https://example.com/contact\"}]}"
|
|
272
253
|
]
|
|
273
254
|
]
|
|
274
255
|
},
|
|
@@ -307,42 +288,29 @@
|
|
|
307
288
|
"entity": "child",
|
|
308
289
|
"data": {
|
|
309
290
|
"is": "subordinated"
|
|
310
|
-
},
|
|
311
|
-
"nested": [],
|
|
312
|
-
"context": {
|
|
313
|
-
"element": [
|
|
314
|
-
"child",
|
|
315
|
-
0
|
|
316
|
-
]
|
|
317
291
|
}
|
|
318
292
|
}
|
|
319
293
|
],
|
|
320
294
|
"consent": {
|
|
321
295
|
"functional": true
|
|
322
296
|
},
|
|
323
|
-
"id": "
|
|
297
|
+
"id": "e1f2a3b4c5d60003",
|
|
324
298
|
"trigger": "load",
|
|
325
299
|
"entity": "page",
|
|
326
300
|
"action": "view",
|
|
327
301
|
"timestamp": 1700000902000,
|
|
328
302
|
"timing": 3.14,
|
|
329
|
-
"group": "gr0up",
|
|
330
|
-
"count": 1,
|
|
331
|
-
"version": {
|
|
332
|
-
"source": "3.4.2",
|
|
333
|
-
"tagging": 1
|
|
334
|
-
},
|
|
335
303
|
"source": {
|
|
336
|
-
"type": "
|
|
337
|
-
"
|
|
338
|
-
"
|
|
304
|
+
"type": "browser",
|
|
305
|
+
"platform": "web",
|
|
306
|
+
"url": "https://example.com/docs/"
|
|
339
307
|
}
|
|
340
308
|
},
|
|
341
309
|
"out": [
|
|
342
310
|
[
|
|
343
311
|
"sendServer",
|
|
344
312
|
"https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t",
|
|
345
|
-
"{\"data\":[{\"event_name\":\"page view\",\"event_time\":1700000902,\"action_source\":\"WEB\",\"event_id\":\"
|
|
313
|
+
"{\"data\":[{\"event_name\":\"page view\",\"event_time\":1700000902,\"action_source\":\"WEB\",\"event_id\":\"e1f2a3b4c5d60003\",\"user_data\":{},\"custom_data\":{},\"event_source_url\":\"https://example.com/docs/\"}]}"
|
|
346
314
|
]
|
|
347
315
|
]
|
|
348
316
|
},
|
|
@@ -386,22 +354,16 @@
|
|
|
386
354
|
"consent": {
|
|
387
355
|
"functional": true
|
|
388
356
|
},
|
|
389
|
-
"id": "
|
|
357
|
+
"id": "e1f2a3b4c5d60001",
|
|
390
358
|
"trigger": "load",
|
|
391
359
|
"entity": "order",
|
|
392
360
|
"action": "complete",
|
|
393
361
|
"timestamp": 1700000900000,
|
|
394
362
|
"timing": 3.14,
|
|
395
|
-
"group": "gr0up",
|
|
396
|
-
"count": 1,
|
|
397
|
-
"version": {
|
|
398
|
-
"source": "3.4.2",
|
|
399
|
-
"tagging": 1
|
|
400
|
-
},
|
|
401
363
|
"source": {
|
|
402
|
-
"type": "
|
|
403
|
-
"
|
|
404
|
-
"
|
|
364
|
+
"type": "browser",
|
|
365
|
+
"platform": "web",
|
|
366
|
+
"url": "https://shop.example.com/checkout/complete"
|
|
405
367
|
}
|
|
406
368
|
},
|
|
407
369
|
"mapping": {
|
|
@@ -448,7 +410,7 @@
|
|
|
448
410
|
[
|
|
449
411
|
"sendServer",
|
|
450
412
|
"https://tr.snapchat.com/v3/p1x3l1d/events?access_token=s3cr3t",
|
|
451
|
-
"{\"data\":[{\"event_name\":\"PURCHASE\",\"event_time\":1700000900,\"action_source\":\"WEB\",\"event_id\":\"
|
|
413
|
+
"{\"data\":[{\"event_name\":\"PURCHASE\",\"event_time\":1700000900,\"action_source\":\"WEB\",\"event_id\":\"e1f2a3b4c5d60001\",\"user_data\":{\"external_id\":\"fcdec6df4d44dbc637c7c5b58efface52a7f8a88535423430255be0bb89bedd8\"},\"custom_data\":{\"value\":249.99,\"currency\":\"EUR\",\"transaction_id\":\"ORD-300\",\"contents\":[{\"id\":\"SKU-A1\",\"item_price\":124.99,\"quantity\":2}]},\"event_source_url\":\"https://shop.example.com/checkout/complete\"}]}"
|
|
452
414
|
]
|
|
453
415
|
]
|
|
454
416
|
}
|
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
|
+
"version": "4.0.0-next-1777463920154",
|
|
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": "
|
|
38
|
-
"@walkeros/server-core": "
|
|
37
|
+
"@walkeros/core": "4.0.0-next-1777463920154",
|
|
38
|
+
"@walkeros/server-core": "4.0.0-next-1777463920154"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@walkeros/collector": "
|
|
41
|
+
"@walkeros/collector": "4.0.0-next-1777463920154"
|
|
42
42
|
},
|
|
43
43
|
"repository": {
|
|
44
44
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|