@walkeros/server-destination-meta 4.7.0-next-1790245733116 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -21
- package/dist/browser-schemas.js +1 -1
- package/dist/browser-schemas.js.map +1 -1
- package/dist/browser-schemas.mjs +1 -1
- package/dist/browser-schemas.mjs.map +1 -1
- package/dist/dev.d.mts +2 -0
- package/dist/dev.d.ts +2 -0
- 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/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- 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 +26 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,31 +1,43 @@
|
|
|
1
1
|
# @walkeros/server-destination-meta
|
|
2
2
|
|
|
3
|
-
## 4.7.0
|
|
3
|
+
## 4.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 74821ed: New `ip` and `userAgent` settings on the Meta, Pinterest, Snapchat,
|
|
8
|
+
TikTok, Reddit, X (Twitter), Bing, Criteo and Google Data Manager server
|
|
9
|
+
destinations. Requests now send the client IP and user agent in each vendor's
|
|
10
|
+
field by default, read from `ingest.ip`/`ingest.userAgent` or
|
|
11
|
+
`user.ip`/`user.userAgent`. A mapped value still wins; set either setting to
|
|
12
|
+
`false` to opt out.
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
6
15
|
|
|
7
|
-
- ef02916: Customer information is
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
runtime. A `url` without a trailing slash also builds a valid endpoint.
|
|
14
|
-
- Updated dependencies [57788bc]
|
|
16
|
+
- ef02916: Customer information is normalized per Meta's rules before hashing,
|
|
17
|
+
so differently cased or padded emails hash the same. The earlier `user_data`
|
|
18
|
+
hint sent `email` and `phone` unhashed: rename them to `em` and `ph`. Unknown
|
|
19
|
+
`settings.user_data` keys fail validation, unknown mapped keys are dropped
|
|
20
|
+
with a warning, and a `url` without trailing slash works.
|
|
21
|
+
- Updated dependencies [74821ed]
|
|
15
22
|
- Updated dependencies [06b498a]
|
|
16
|
-
- Updated dependencies [
|
|
17
|
-
- Updated dependencies [
|
|
23
|
+
- Updated dependencies [74821ed]
|
|
24
|
+
- Updated dependencies [64b06de]
|
|
25
|
+
- Updated dependencies [4b4937f]
|
|
26
|
+
- Updated dependencies [74821ed]
|
|
27
|
+
- Updated dependencies [74821ed]
|
|
28
|
+
- Updated dependencies [74821ed]
|
|
18
29
|
- Updated dependencies [06b498a]
|
|
19
|
-
- Updated dependencies [
|
|
20
|
-
- Updated dependencies [
|
|
21
|
-
- Updated dependencies [
|
|
22
|
-
- Updated dependencies [
|
|
23
|
-
- Updated dependencies [
|
|
24
|
-
- Updated dependencies [
|
|
25
|
-
- Updated dependencies [
|
|
26
|
-
- Updated dependencies [
|
|
27
|
-
|
|
28
|
-
- @walkeros/
|
|
30
|
+
- Updated dependencies [74821ed]
|
|
31
|
+
- Updated dependencies [74821ed]
|
|
32
|
+
- Updated dependencies [74821ed]
|
|
33
|
+
- Updated dependencies [74821ed]
|
|
34
|
+
- Updated dependencies [74821ed]
|
|
35
|
+
- Updated dependencies [e860006]
|
|
36
|
+
- Updated dependencies [74821ed]
|
|
37
|
+
- Updated dependencies [74821ed]
|
|
38
|
+
- Updated dependencies [4f89234]
|
|
39
|
+
- @walkeros/core@4.7.0
|
|
40
|
+
- @walkeros/server-core@4.7.0
|
|
29
41
|
|
|
30
42
|
## 4.6.1
|
|
31
43
|
|
package/dist/browser-schemas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,browser_schemas_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(browser_schemas_exports,{schemas:()=>schemas2}),module.exports=(mod=browser_schemas_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_dev4=require("@walkeros/core/dev"),import_dev2=require("@walkeros/core/dev"),import_dev=require("@walkeros/core/dev"),ActionSourceSchema=import_dev.z.enum(["email","website","app","phone_call","chat","physical_store","system_generated","business_messaging","other"]),
|
|
1
|
+
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,browser_schemas_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(browser_schemas_exports,{schemas:()=>schemas2}),module.exports=(mod=browser_schemas_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_dev4=require("@walkeros/core/dev"),import_dev2=require("@walkeros/core/dev"),import_dev=require("@walkeros/core/dev"),ActionSourceSchema=import_dev.z.enum(["email","website","app","phone_call","chat","physical_store","system_generated","business_messaging","other"]),InputSchema=(import_dev.z.union([import_dev.z.enum(["AddPaymentInfo","AddToCart","AddToWishlist","CompleteRegistration","Contact","CustomizeProduct","Donate","FindLocation","InitiateCheckout","Lead","Purchase","Schedule","Search","StartTrial","SubmitApplication","Subscribe","ViewContent"]),import_dev.z.string()]),import_dev2.z.union([import_dev2.schemas.MappingSchemas.ValueSchema,import_dev2.z.literal(!1)])),SettingsSchema=import_dev2.z.object({accessToken:import_dev2.z.string().min(1).describe("Meta access token for Conversions API authentication (like your_access_token)"),pixelId:import_dev2.z.string().regex(/^[0-9]+$/,"Pixel ID must contain only digits").describe("Meta Pixel ID from your Facebook Business account (like 1234567890)"),action_source:ActionSourceSchema.describe("Source of the event (website, app, phone_call, etc.) (like website)").optional(),doNotHash:import_dev2.z.array(import_dev2.z.string()).describe("user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])").optional(),test_event_code:import_dev2.z.string().describe("Test event code for debugging Meta Conversions API events (like TEST12345)").optional(),url:import_dev2.z.string().url().describe("Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)").optional(),user_data:import_dev2.z.partialRecord(import_dev2.z.enum(["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"]),import_dev2.schemas.MappingSchemas.ValueSchema).describe("Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })").optional(),ip:InputSchema.describe('Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off. A mapped user_data.client_ip_address wins.').optional(),userAgent:InputSchema.describe('Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped user_data.client_user_agent wins.').optional()}),MappingSchema=require("@walkeros/core/dev").z.object({}),schemas2={settings:(0,import_dev4.zodToSchema)(SettingsSchema),mapping:(0,import_dev4.zodToSchema)(MappingSchema)};//# sourceMappingURL=browser-schemas.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/browser-schemas.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { settings, mapping } from './schemas';\n\nexport const schemas = {\n settings,\n mapping,\n};\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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,iBAAAA;AAAA;AAAA;;;ACAA,IAAAC,cAA4B;;;ACA5B,IAAAC,cAA2B;;;ACGpB,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC9BA,iBAAkB;AAOX,IAAM,qBAAqB,aAAE,KAAK;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,IAAM,kBAAkB,aAAE,MAAM;AAAA,EACrC,aAAE,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,EACF,CAAC;AAAA,EACD,aAAE,OAAO;AAAA;AACX,CAAC;;;
|
|
1
|
+
{"version":3,"sources":["../src/browser-schemas.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { settings, mapping } from './schemas';\n\nexport const schemas = {\n settings,\n mapping,\n};\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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nconst InputSchema = z.union([\n schemas.MappingSchemas.ValueSchema,\n z.literal(false),\n]);\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n ip: InputSchema.describe(\n 'Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.client_ip_address wins.',\n ).optional(),\n userAgent: InputSchema.describe(\n 'Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.client_user_agent wins.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,iBAAAA;AAAA;AAAA;;;ACAA,IAAAC,cAA4B;;;ACA5B,IAAAC,cAA2B;;;ACGpB,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC9BA,iBAAkB;AAOX,IAAM,qBAAqB,aAAE,KAAK;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,IAAM,kBAAkB,aAAE,MAAM;AAAA,EACrC,aAAE,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,EACF,CAAC;AAAA,EACD,aAAE,OAAO;AAAA;AACX,CAAC;;;AFxCD,IAAM,cAAc,cAAE,MAAM;AAAA,EAC1B,oBAAQ,eAAe;AAAA,EACvB,cAAE,QAAQ,KAAK;AACjB,CAAC;AAEM,IAAM,iBAAiB,cAAE,OAAO;AAAA,EACrC,aAAa,cACV,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,SAAS,cACN,OAAO,EACP,MAAM,YAAY,mCAAmC,EACrD;AAAA,IACC;AAAA,EACF;AAAA,EACF,eAAe,mBAAmB;AAAA,IAChC;AAAA,EACF,EAAE,SAAS;AAAA,EACX,WAAW,cACR,MAAM,cAAE,OAAO,CAAC,EAChB;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,iBAAiB,cACd,OAAO,EACP;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,KAAK,cACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,WAAW,cACR,cAAc,cAAE,KAAK,YAAY,GAAG,oBAAQ,eAAe,WAAW,EACtE;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,IAAI,YAAY;AAAA,IACd;AAAA,EACF,EAAE,SAAS;AAAA,EACX,WAAW,YAAY;AAAA,IACrB;AAAA,EACF,EAAE,SAAS;AACb,CAAC;;;AGxDD,IAAAC,cAAkB;AAMX,IAAM,gBAAgB,cAAE,OAAO,CAAC,CAAC;;;AJIjC,IAAM,eAAW,yBAAY,cAAc;AAC3C,IAAM,cAAU,yBAAY,aAAa;;;ADPzC,IAAMC,WAAU;AAAA,EACrB;AAAA,EACA;AACF;","names":["schemas","import_dev","import_dev","import_dev","schemas"]}
|
package/dist/browser-schemas.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{zodToSchema}from"@walkeros/core/dev";import{schemas,z as z2}from"@walkeros/core/dev";import{z}from"@walkeros/core/dev";var ActionSourceSchema=z.enum(["email","website","app","phone_call","chat","physical_store","system_generated","business_messaging","other"]),
|
|
1
|
+
import{zodToSchema}from"@walkeros/core/dev";import{schemas,z as z2}from"@walkeros/core/dev";import{z}from"@walkeros/core/dev";var ActionSourceSchema=z.enum(["email","website","app","phone_call","chat","physical_store","system_generated","business_messaging","other"]),InputSchema=(z.union([z.enum(["AddPaymentInfo","AddToCart","AddToWishlist","CompleteRegistration","Contact","CustomizeProduct","Donate","FindLocation","InitiateCheckout","Lead","Purchase","Schedule","Search","StartTrial","SubmitApplication","Subscribe","ViewContent"]),z.string()]),z2.union([schemas.MappingSchemas.ValueSchema,z2.literal(!1)])),SettingsSchema=z2.object({accessToken:z2.string().min(1).describe("Meta access token for Conversions API authentication (like your_access_token)"),pixelId:z2.string().regex(/^[0-9]+$/,"Pixel ID must contain only digits").describe("Meta Pixel ID from your Facebook Business account (like 1234567890)"),action_source:ActionSourceSchema.describe("Source of the event (website, app, phone_call, etc.) (like website)").optional(),doNotHash:z2.array(z2.string()).describe("user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])").optional(),test_event_code:z2.string().describe("Test event code for debugging Meta Conversions API events (like TEST12345)").optional(),url:z2.string().url().describe("Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)").optional(),user_data:z2.partialRecord(z2.enum(["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"]),schemas.MappingSchemas.ValueSchema).describe("Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })").optional(),ip:InputSchema.describe('Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off. A mapped user_data.client_ip_address wins.').optional(),userAgent:InputSchema.describe('Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped user_data.client_user_agent wins.').optional()});import{z as z3}from"@walkeros/core/dev";var MappingSchema=z3.object({}),schemas2={settings:zodToSchema(SettingsSchema),mapping:zodToSchema(MappingSchema)};export{schemas2 as schemas};//# sourceMappingURL=browser-schemas.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.ts","../src/browser-schemas.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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { settings, mapping } from './schemas';\n\nexport const schemas = {\n settings,\n mapping,\n};\n"],"mappings":";AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,SAAS,KAAAA,UAAS;;;ACGpB,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC9BA,SAAS,SAAS;AAOX,IAAM,qBAAqB,EAAE,KAAK;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,IAAM,kBAAkB,EAAE,MAAM;AAAA,EACrC,EAAE,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,EACF,CAAC;AAAA,EACD,EAAE,OAAO;AAAA;AACX,CAAC;;;
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.ts","../src/browser-schemas.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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nconst InputSchema = z.union([\n schemas.MappingSchemas.ValueSchema,\n z.literal(false),\n]);\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n ip: InputSchema.describe(\n 'Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.client_ip_address wins.',\n ).optional(),\n userAgent: InputSchema.describe(\n 'Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.client_user_agent wins.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { settings, mapping } from './schemas';\n\nexport const schemas = {\n settings,\n mapping,\n};\n"],"mappings":";AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,SAAS,KAAAA,UAAS;;;ACGpB,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC9BA,SAAS,SAAS;AAOX,IAAM,qBAAqB,EAAE,KAAK;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,IAAM,kBAAkB,EAAE,MAAM;AAAA,EACrC,EAAE,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,EACF,CAAC;AAAA,EACD,EAAE,OAAO;AAAA;AACX,CAAC;;;AFxCD,IAAM,cAAcC,GAAE,MAAM;AAAA,EAC1B,QAAQ,eAAe;AAAA,EACvBA,GAAE,QAAQ,KAAK;AACjB,CAAC;AAEM,IAAM,iBAAiBA,GAAE,OAAO;AAAA,EACrC,aAAaA,GACV,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,SAASA,GACN,OAAO,EACP,MAAM,YAAY,mCAAmC,EACrD;AAAA,IACC;AAAA,EACF;AAAA,EACF,eAAe,mBAAmB;AAAA,IAChC;AAAA,EACF,EAAE,SAAS;AAAA,EACX,WAAWA,GACR,MAAMA,GAAE,OAAO,CAAC,EAChB;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,iBAAiBA,GACd,OAAO,EACP;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,KAAKA,GACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,WAAWA,GACR,cAAcA,GAAE,KAAK,YAAY,GAAG,QAAQ,eAAe,WAAW,EACtE;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,IAAI,YAAY;AAAA,IACd;AAAA,EACF,EAAE,SAAS;AAAA,EACX,WAAW,YAAY;AAAA,IACrB;AAAA,EACF,EAAE,SAAS;AACb,CAAC;;;AGxDD,SAAS,KAAAC,UAAS;AAMX,IAAM,gBAAgBA,GAAE,OAAO,CAAC,CAAC;;;AJIjC,IAAM,WAAW,YAAY,cAAc;AAC3C,IAAM,UAAU,YAAY,aAAa;;;AKPzC,IAAMC,WAAU;AAAA,EACrB;AAAA,EACA;AACF;","names":["z","z","z","schemas"]}
|
package/dist/dev.d.mts
CHANGED
|
@@ -88,6 +88,8 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
88
88
|
ig_sid: "ig_sid";
|
|
89
89
|
fbclid: "fbclid";
|
|
90
90
|
}> & z.core.$partial, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
91
|
+
ip: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
|
|
92
|
+
userAgent: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
|
|
91
93
|
}, z.core.$strip>;
|
|
92
94
|
type Settings = z.infer<typeof SettingsSchema>;
|
|
93
95
|
|
package/dist/dev.d.ts
CHANGED
|
@@ -88,6 +88,8 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
88
88
|
ig_sid: "ig_sid";
|
|
89
89
|
fbclid: "fbclid";
|
|
90
90
|
}> & z.core.$partial, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
91
|
+
ip: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
|
|
92
|
+
userAgent: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
|
|
91
93
|
}, z.core.$strip>;
|
|
92
94
|
type Settings = z.infer<typeof SettingsSchema>;
|
|
93
95
|
|
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,s=(e,a)=>{for(var r in a)t(e,r,{get:a[r],enumerable:!0})},n={};s(n,{examples:()=>f,schemas:()=>o}),module.exports=(e=n,((e,s,n,o)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let c of r(s))i.call(e,c)||c===n||t(e,c,{get:()=>s[c],enumerable:!(o=a(s,c))||o.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o={};s(o,{ActionSourceSchema:()=>l,EventNameSchema:()=>p,MappingSchema:()=>h,SettingsSchema:()=>_,mapping:()=>v,settings:()=>b});var c=require("@walkeros/core/dev"),d=require("@walkeros/core/dev"),u=require("@walkeros/core/dev"),l=u.z.enum(["email","website","app","phone_call","chat","physical_store","system_generated","business_messaging","other"]),p=u.z.union([u.z.enum(["AddPaymentInfo","AddToCart","AddToWishlist","CompleteRegistration","Contact","CustomizeProduct","Donate","FindLocation","InitiateCheckout","Lead","Purchase","Schedule","Search","StartTrial","SubmitApplication","Subscribe","ViewContent"]),u.z.string()]),m=d.z.union([d.schemas.MappingSchemas.ValueSchema,d.z.literal(!1)]),_=d.z.object({accessToken:d.z.string().min(1).describe("Meta access token for Conversions API authentication (like your_access_token)"),pixelId:d.z.string().regex(/^[0-9]+$/,"Pixel ID must contain only digits").describe("Meta Pixel ID from your Facebook Business account (like 1234567890)"),action_source:l.describe("Source of the event (website, app, phone_call, etc.) (like website)").optional(),doNotHash:d.z.array(d.z.string()).describe("user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])").optional(),test_event_code:d.z.string().describe("Test event code for debugging Meta Conversions API events (like TEST12345)").optional(),url:d.z.string().url().describe("Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)").optional(),user_data:d.z.partialRecord(d.z.enum(["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"]),d.schemas.MappingSchemas.ValueSchema).describe("Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })").optional(),ip:m.describe('Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off. A mapped user_data.client_ip_address wins.').optional(),userAgent:m.describe('Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped user_data.client_user_agent wins.').optional()}),h=require("@walkeros/core/dev").z.object({}),b=(0,c.zodToSchema)(_),v=(0,c.zodToSchema)(h),f={};s(f,{env:()=>g,step:()=>S});var g={};s(g,{push:()=>y,simulation:()=>w});var y={sendServer:async function(e,t,a){return{ok:!0,data:{events_received:1,messages:[],fbtrace_id:"mock-trace-id"}}}},w=["sendServer"],S={};s(S,{lead:()=>P,purchase:()=>A,purchaseWithClickAttribution:()=>C});var k=require("@walkeros/core"),z="https://graph.facebook.com/v22.0/1234567890/events",x={headers:{Authorization:"Bearer s3cr3t"}},A={title:"Purchase",description:"A completed order is sent to the Meta Conversions API as a Purchase event with value, currency, and contents.",in:(0,k.getEvent)("order complete",{id:"c1d2e3f4a5b60001",timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",price:129.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com"}}),mapping:{name:"Purchase",data:{map:{order_id:"data.id",currency:{key:"data.currency",value:"EUR"},value:"data.total",contents:{loop:["nested",{condition:e=>"object"==typeof e&&null!==e&&"entity"in e&&"product"===e.entity,map:{id:"data.id",item_price:"data.price",quantity:{key:"data.quantity",value:1}}}]},num_items:{fn:e=>e.nested.filter(e=>"product"===e.entity).length}}}},out:[["sendServer",z,JSON.stringify({data:[{event_name:"Purchase",event_id:"c1d2e3f4a5b60001",event_time:1700000900,action_source:"website",order_id:"ORD-300",currency:"EUR",value:249.99,contents:[{id:"SKU-A1",item_price:129.99,quantity:2}],num_items:1,user_data:{},event_source_url:"https://shop.example.com"}]}),x]]},P={title:"Form submit",description:"A form submission is forwarded to Meta CAPI as a custom event with the event source URL.",in:(0,k.getEvent)("form submit",{id:"c1d2e3f4a5b60002",timestamp:1700000901e3,data:{type:"newsletter"},user:{email:"user@example.com"},source:{type:"browser",platform:"web",url:"https://example.com"}}),mapping:void 0,out:[["sendServer",z,JSON.stringify({data:[{event_name:"form submit",event_id:"c1d2e3f4a5b60002",event_time:1700000901,action_source:"website",user_data:{},event_source_url:"https://example.com"}]}),x]]},C={title:"Purchase with fbclid",description:"A purchase is sent to Meta CAPI with an external_id and a formatted fbc click id for ads attribution.",in:(0,k.getEvent)("order complete",{id:"c1d2e3f4a5b60003",timestamp:1700000902e3,data:{id:"ORD-700",total:89.99,currency:"USD"},user:{id:"cust-42"},context:{fbclid:["abc123xyz",0]},source:{type:"browser",platform:"web",url:"https://shop.example.com"}}),mapping:{name:"Purchase",data:{map:{currency:{key:"data.currency",value:"EUR"},value:"data.total",order_id:"data.id",user_data:{map:{external_id:"user.id",fbclid:"context.fbclid.0"}}}}},out:[["sendServer",z,JSON.stringify({data:[{event_name:"Purchase",event_id:"c1d2e3f4a5b60003",event_time:1700000902,action_source:"website",currency:"USD",value:89.99,order_id:"ORD-700",user_data:{external_id:"8a3c5a67cad508582b5edf6b8352cea3ffbad7f44812c1a736b4444c0f5746aa",fbc:"fb.1.1700000902000.abc123xyz"},event_source_url:"https://shop.example.com"}]}),x]]};//# 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/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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","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 Meta Conversions API destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\n/**\n * Mock sendServer function that simulates successful HTTP responses\n */\nasync function mockSendServer(\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n): Promise<SendResponse> {\n // Simulate successful Meta API response\n return {\n ok: true,\n data: {\n events_received: 1,\n messages: [],\n fbtrace_id: 'mock-trace-id',\n },\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing Meta Conversions API events without making\n * actual HTTP requests to Facebook's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Meta Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body, options)`\n * where `url` is `${settings.url}/${settings.pixelId}/events`, `body` is the\n * JSON-stringified `{ data: [serverEvent] }` payload, and `options` carries the\n * access token in an `Authorization: Bearer` header (never in the URL).\n *\n * The public name users see when inspecting the destination is `sendServer`,\n * so each `out` tuple is `['sendServer', url, body, options]` with `body` as\n * the already-stringified JSON payload (mirroring the actual call signature).\n *\n * Functions in mappings are published as source code, so they must not use\n * imported helpers.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = '1234567890'`,\n * so every endpoint resolves to:\n * https://graph.facebook.com/v22.0/1234567890/events\n * with header `Authorization: Bearer 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_id\n * 3. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 4. action_source\n * 5. ...mapped event data (currency, value, etc.)\n * 6. user_data (hashed per Meta's PII requirements)\n * 7. event_source_url (appended after hash when action_source === 'website')\n */\nconst ENDPOINT = 'https://graph.facebook.com/v22.0/1234567890/events';\n\nconst OPTIONS = { headers: { Authorization: 'Bearer s3cr3t' } };\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Meta Conversions API as a Purchase event with value, currency, and contents.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60001',\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n { entity: 'product', data: { id: 'SKU-A1', price: 129.99, quantity: 2 } },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n order_id: 'data.id',\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n typeof entity === 'object' &&\n entity !== null &&\n 'entity' in entity &&\n 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 num_items: {\n fn: (event: unknown) =>\n (event as WalkerOS.Event).nested.filter(\n (item) => item.entity === 'product',\n ).length,\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60001',\n event_time: 1700000900,\n action_source: 'website',\n order_id: 'ORD-300',\n currency: 'EUR',\n value: 249.99,\n contents: [{ id: 'SKU-A1', item_price: 129.99, quantity: 2 }],\n num_items: 1,\n user_data: {},\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Form submit',\n description:\n 'A form submission is forwarded to Meta CAPI as a custom event with the event source URL.',\n in: getEvent('form submit', {\n id: 'c1d2e3f4a5b60002',\n timestamp: 1700000901000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'form submit',\n event_id: 'c1d2e3f4a5b60002',\n event_time: 1700000901,\n action_source: 'website',\n user_data: {},\n event_source_url: 'https://example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const purchaseWithClickAttribution: Flow.StepExample = {\n title: 'Purchase with fbclid',\n description:\n 'A purchase is sent to Meta CAPI with an external_id and a formatted fbc click id for ads attribution.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60003',\n timestamp: 1700000902000,\n data: { id: 'ORD-700', total: 89.99, currency: 'USD' },\n user: { id: 'cust-42' },\n context: { fbclid: ['abc123xyz', 0] },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n order_id: 'data.id',\n user_data: {\n map: {\n external_id: 'user.id',\n fbclid: 'context.fbclid.0',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60003',\n event_time: 1700000902,\n action_source: 'website',\n currency: 'USD',\n value: 89.99,\n order_id: 'ORD-700',\n user_data: {\n // sha256('cust-42')\n external_id:\n '8a3c5a67cad508582b5edf6b8352cea3ffbad7f44812c1a736b4444c0f5746aa',\n // fb.subdomainIndex.creationTime.fbclid, creationTime in milliseconds\n fbc: 'fb.1.1700000902000.abc123xyz',\n },\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n"],"mappings":"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","names":["import_dev","import_dev","import_dev"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nconst InputSchema = z.union([\n schemas.MappingSchemas.ValueSchema,\n z.literal(false),\n]);\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n ip: InputSchema.describe(\n 'Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.client_ip_address wins.',\n ).optional(),\n userAgent: InputSchema.describe(\n 'Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.client_user_agent wins.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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","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 Meta Conversions API destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\n/**\n * Mock sendServer function that simulates successful HTTP responses\n */\nasync function mockSendServer(\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n): Promise<SendResponse> {\n // Simulate successful Meta API response\n return {\n ok: true,\n data: {\n events_received: 1,\n messages: [],\n fbtrace_id: 'mock-trace-id',\n },\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing Meta Conversions API events without making\n * actual HTTP requests to Facebook's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Meta Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body, options)`\n * where `url` is `${settings.url}/${settings.pixelId}/events`, `body` is the\n * JSON-stringified `{ data: [serverEvent] }` payload, and `options` carries the\n * access token in an `Authorization: Bearer` header (never in the URL).\n *\n * The public name users see when inspecting the destination is `sendServer`,\n * so each `out` tuple is `['sendServer', url, body, options]` with `body` as\n * the already-stringified JSON payload (mirroring the actual call signature).\n *\n * Functions in mappings are published as source code, so they must not use\n * imported helpers.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = '1234567890'`,\n * so every endpoint resolves to:\n * https://graph.facebook.com/v22.0/1234567890/events\n * with header `Authorization: Bearer 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_id\n * 3. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 4. action_source\n * 5. ...mapped event data (currency, value, etc.)\n * 6. user_data (hashed per Meta's PII requirements)\n * 7. event_source_url (appended after hash when action_source === 'website')\n */\nconst ENDPOINT = 'https://graph.facebook.com/v22.0/1234567890/events';\n\nconst OPTIONS = { headers: { Authorization: 'Bearer s3cr3t' } };\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Meta Conversions API as a Purchase event with value, currency, and contents.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60001',\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n { entity: 'product', data: { id: 'SKU-A1', price: 129.99, quantity: 2 } },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n order_id: 'data.id',\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n typeof entity === 'object' &&\n entity !== null &&\n 'entity' in entity &&\n 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 num_items: {\n fn: (event: unknown) =>\n (event as WalkerOS.Event).nested.filter(\n (item) => item.entity === 'product',\n ).length,\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60001',\n event_time: 1700000900,\n action_source: 'website',\n order_id: 'ORD-300',\n currency: 'EUR',\n value: 249.99,\n contents: [{ id: 'SKU-A1', item_price: 129.99, quantity: 2 }],\n num_items: 1,\n user_data: {},\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Form submit',\n description:\n 'A form submission is forwarded to Meta CAPI as a custom event with the event source URL.',\n in: getEvent('form submit', {\n id: 'c1d2e3f4a5b60002',\n timestamp: 1700000901000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'form submit',\n event_id: 'c1d2e3f4a5b60002',\n event_time: 1700000901,\n action_source: 'website',\n user_data: {},\n event_source_url: 'https://example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const purchaseWithClickAttribution: Flow.StepExample = {\n title: 'Purchase with fbclid',\n description:\n 'A purchase is sent to Meta CAPI with an external_id and a formatted fbc click id for ads attribution.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60003',\n timestamp: 1700000902000,\n data: { id: 'ORD-700', total: 89.99, currency: 'USD' },\n user: { id: 'cust-42' },\n context: { fbclid: ['abc123xyz', 0] },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n order_id: 'data.id',\n user_data: {\n map: {\n external_id: 'user.id',\n fbclid: 'context.fbclid.0',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60003',\n event_time: 1700000902,\n action_source: 'website',\n currency: 'USD',\n value: 89.99,\n order_id: 'ORD-700',\n user_data: {\n // sha256('cust-42')\n external_id:\n '8a3c5a67cad508582b5edf6b8352cea3ffbad7f44812c1a736b4444c0f5746aa',\n // fb.subdomainIndex.creationTime.fbclid, creationTime in milliseconds\n fbc: 'fb.1.1700000902000.abc123xyz',\n },\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\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
|
|
1
|
+
var e=Object.defineProperty,t=(t,a)=>{for(var i in a)e(t,i,{get:a[i],enumerable:!0})},a={};t(a,{ActionSourceSchema:()=>o,EventNameSchema:()=>c,MappingSchema:()=>p,SettingsSchema:()=>u,mapping:()=>_,settings:()=>m});import{zodToSchema as i}from"@walkeros/core/dev";import{schemas as r,z as s}from"@walkeros/core/dev";import{z as n}from"@walkeros/core/dev";var o=n.enum(["email","website","app","phone_call","chat","physical_store","system_generated","business_messaging","other"]),c=n.union([n.enum(["AddPaymentInfo","AddToCart","AddToWishlist","CompleteRegistration","Contact","CustomizeProduct","Donate","FindLocation","InitiateCheckout","Lead","Purchase","Schedule","Search","StartTrial","SubmitApplication","Subscribe","ViewContent"]),n.string()]),d=s.union([r.MappingSchemas.ValueSchema,s.literal(!1)]),u=s.object({accessToken:s.string().min(1).describe("Meta access token for Conversions API authentication (like your_access_token)"),pixelId:s.string().regex(/^[0-9]+$/,"Pixel ID must contain only digits").describe("Meta Pixel ID from your Facebook Business account (like 1234567890)"),action_source:o.describe("Source of the event (website, app, phone_call, etc.) (like website)").optional(),doNotHash:s.array(s.string()).describe("user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])").optional(),test_event_code:s.string().describe("Test event code for debugging Meta Conversions API events (like TEST12345)").optional(),url:s.string().url().describe("Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)").optional(),user_data:s.partialRecord(s.enum(["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"]),r.MappingSchemas.ValueSchema).describe("Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })").optional(),ip:d.describe('Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off. A mapped user_data.client_ip_address wins.').optional(),userAgent:d.describe('Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped user_data.client_user_agent wins.').optional()});import{z as l}from"@walkeros/core/dev";var p=l.object({}),m=i(u),_=i(p),h={};t(h,{env:()=>b,step:()=>g});var b={};t(b,{push:()=>v,simulation:()=>f});var v={sendServer:async function(e,t,a){return{ok:!0,data:{events_received:1,messages:[],fbtrace_id:"mock-trace-id"}}}},f=["sendServer"],g={};t(g,{lead:()=>x,purchase:()=>k,purchaseWithClickAttribution:()=>A});import{getEvent as y}from"@walkeros/core";var w="https://graph.facebook.com/v22.0/1234567890/events",S={headers:{Authorization:"Bearer s3cr3t"}},k={title:"Purchase",description:"A completed order is sent to the Meta Conversions API as a Purchase event with value, currency, and contents.",in:y("order complete",{id:"c1d2e3f4a5b60001",timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",price:129.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com"}}),mapping:{name:"Purchase",data:{map:{order_id:"data.id",currency:{key:"data.currency",value:"EUR"},value:"data.total",contents:{loop:["nested",{condition:e=>"object"==typeof e&&null!==e&&"entity"in e&&"product"===e.entity,map:{id:"data.id",item_price:"data.price",quantity:{key:"data.quantity",value:1}}}]},num_items:{fn:e=>e.nested.filter(e=>"product"===e.entity).length}}}},out:[["sendServer",w,JSON.stringify({data:[{event_name:"Purchase",event_id:"c1d2e3f4a5b60001",event_time:1700000900,action_source:"website",order_id:"ORD-300",currency:"EUR",value:249.99,contents:[{id:"SKU-A1",item_price:129.99,quantity:2}],num_items:1,user_data:{},event_source_url:"https://shop.example.com"}]}),S]]},x={title:"Form submit",description:"A form submission is forwarded to Meta CAPI as a custom event with the event source URL.",in:y("form submit",{id:"c1d2e3f4a5b60002",timestamp:1700000901e3,data:{type:"newsletter"},user:{email:"user@example.com"},source:{type:"browser",platform:"web",url:"https://example.com"}}),mapping:void 0,out:[["sendServer",w,JSON.stringify({data:[{event_name:"form submit",event_id:"c1d2e3f4a5b60002",event_time:1700000901,action_source:"website",user_data:{},event_source_url:"https://example.com"}]}),S]]},A={title:"Purchase with fbclid",description:"A purchase is sent to Meta CAPI with an external_id and a formatted fbc click id for ads attribution.",in:y("order complete",{id:"c1d2e3f4a5b60003",timestamp:1700000902e3,data:{id:"ORD-700",total:89.99,currency:"USD"},user:{id:"cust-42"},context:{fbclid:["abc123xyz",0]},source:{type:"browser",platform:"web",url:"https://shop.example.com"}}),mapping:{name:"Purchase",data:{map:{currency:{key:"data.currency",value:"EUR"},value:"data.total",order_id:"data.id",user_data:{map:{external_id:"user.id",fbclid:"context.fbclid.0"}}}}},out:[["sendServer",w,JSON.stringify({data:[{event_name:"Purchase",event_id:"c1d2e3f4a5b60003",event_time:1700000902,action_source:"website",currency:"USD",value:89.99,order_id:"ORD-700",user_data:{external_id:"8a3c5a67cad508582b5edf6b8352cea3ffbad7f44812c1a736b4444c0f5746aa",fbc:"fb.1.1700000902000.abc123xyz"},event_source_url:"https://shop.example.com"}]}),S]]};export{h 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/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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","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 Meta Conversions API destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\n/**\n * Mock sendServer function that simulates successful HTTP responses\n */\nasync function mockSendServer(\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n): Promise<SendResponse> {\n // Simulate successful Meta API response\n return {\n ok: true,\n data: {\n events_received: 1,\n messages: [],\n fbtrace_id: 'mock-trace-id',\n },\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing Meta Conversions API events without making\n * actual HTTP requests to Facebook's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Meta Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body, options)`\n * where `url` is `${settings.url}/${settings.pixelId}/events`, `body` is the\n * JSON-stringified `{ data: [serverEvent] }` payload, and `options` carries the\n * access token in an `Authorization: Bearer` header (never in the URL).\n *\n * The public name users see when inspecting the destination is `sendServer`,\n * so each `out` tuple is `['sendServer', url, body, options]` with `body` as\n * the already-stringified JSON payload (mirroring the actual call signature).\n *\n * Functions in mappings are published as source code, so they must not use\n * imported helpers.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = '1234567890'`,\n * so every endpoint resolves to:\n * https://graph.facebook.com/v22.0/1234567890/events\n * with header `Authorization: Bearer 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_id\n * 3. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 4. action_source\n * 5. ...mapped event data (currency, value, etc.)\n * 6. user_data (hashed per Meta's PII requirements)\n * 7. event_source_url (appended after hash when action_source === 'website')\n */\nconst ENDPOINT = 'https://graph.facebook.com/v22.0/1234567890/events';\n\nconst OPTIONS = { headers: { Authorization: 'Bearer s3cr3t' } };\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Meta Conversions API as a Purchase event with value, currency, and contents.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60001',\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n { entity: 'product', data: { id: 'SKU-A1', price: 129.99, quantity: 2 } },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n order_id: 'data.id',\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n typeof entity === 'object' &&\n entity !== null &&\n 'entity' in entity &&\n 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 num_items: {\n fn: (event: unknown) =>\n (event as WalkerOS.Event).nested.filter(\n (item) => item.entity === 'product',\n ).length,\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60001',\n event_time: 1700000900,\n action_source: 'website',\n order_id: 'ORD-300',\n currency: 'EUR',\n value: 249.99,\n contents: [{ id: 'SKU-A1', item_price: 129.99, quantity: 2 }],\n num_items: 1,\n user_data: {},\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Form submit',\n description:\n 'A form submission is forwarded to Meta CAPI as a custom event with the event source URL.',\n in: getEvent('form submit', {\n id: 'c1d2e3f4a5b60002',\n timestamp: 1700000901000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'form submit',\n event_id: 'c1d2e3f4a5b60002',\n event_time: 1700000901,\n action_source: 'website',\n user_data: {},\n event_source_url: 'https://example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const purchaseWithClickAttribution: Flow.StepExample = {\n title: 'Purchase with fbclid',\n description:\n 'A purchase is sent to Meta CAPI with an external_id and a formatted fbc click id for ads attribution.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60003',\n timestamp: 1700000902000,\n data: { id: 'ORD-700', total: 89.99, currency: 'USD' },\n user: { id: 'cust-42' },\n context: { fbclid: ['abc123xyz', 0] },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n order_id: 'data.id',\n user_data: {\n map: {\n external_id: 'user.id',\n fbclid: 'context.fbclid.0',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60003',\n event_time: 1700000902,\n action_source: 'website',\n currency: 'USD',\n value: 89.99,\n order_id: 'ORD-700',\n user_data: {\n // sha256('cust-42')\n external_id:\n '8a3c5a67cad508582b5edf6b8352cea3ffbad7f44812c1a736b4444c0f5746aa',\n // fb.subdomainIndex.creationTime.fbclid, creationTime in milliseconds\n fbc: 'fb.1.1700000902000.abc123xyz',\n },\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n"],"mappings":"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","names":["z","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/userData.ts","../src/schemas/primitives.ts","../src/schemas/mapping.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 { schemas, z } from '@walkeros/core/dev';\nimport { userDataKeys } from '../userData';\nimport { ActionSourceSchema } from './primitives';\n\nconst InputSchema = z.union([\n schemas.MappingSchemas.ValueSchema,\n z.literal(false),\n]);\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'Meta access token for Conversions API authentication (like your_access_token)',\n ),\n pixelId: z\n .string()\n .regex(/^[0-9]+$/, 'Pixel ID must contain only digits')\n .describe(\n 'Meta Pixel ID from your Facebook Business account (like 1234567890)',\n ),\n action_source: ActionSourceSchema.describe(\n 'Source of the event (website, app, phone_call, etc.) (like website)',\n ).optional(),\n doNotHash: z\n .array(z.string())\n .describe(\n \"user_data keys to send without normalizing and hashing, for values that are already hashed. Only em, ph, fn, ln, db, ge, ct, st, zp, country and external_id are hashed (like ['external_id'])\",\n )\n .optional(),\n test_event_code: z\n .string()\n .describe(\n 'Test event code for debugging Meta Conversions API events (like TEST12345)',\n )\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom URL for Meta Conversions API endpoint (like https://graph.facebook.com/v22.0)',\n )\n .optional(),\n user_data: z\n .partialRecord(z.enum(userDataKeys), schemas.MappingSchemas.ValueSchema)\n .describe(\n \"Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })\",\n )\n .optional(),\n ip: InputSchema.describe(\n 'Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.client_ip_address wins.',\n ).optional(),\n userAgent: InputSchema.describe(\n 'Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.client_user_agent wins.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Action Source Enum\n * Where the conversion event took place\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport const ActionSourceSchema = z.enum([\n 'email',\n 'website',\n 'app',\n 'phone_call',\n 'chat',\n 'physical_store',\n 'system_generated',\n 'business_messaging',\n 'other',\n]);\n\n/**\n * Event Name\n * Standard Meta event names or custom event identifiers\n */\nexport const EventNameSchema = z.union([\n z.enum([\n 'AddPaymentInfo',\n 'AddToCart',\n 'AddToWishlist',\n 'CompleteRegistration',\n 'Contact',\n 'CustomizeProduct',\n 'Donate',\n 'FindLocation',\n 'InitiateCheckout',\n 'Lead',\n 'Purchase',\n 'Schedule',\n 'Search',\n 'StartTrial',\n 'SubmitApplication',\n 'Subscribe',\n 'ViewContent',\n ]),\n z.string(), // Allow custom event names\n]);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Meta Conversions API Mapping Schema\n * Meta 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","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 Meta Conversions API destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\n/**\n * Mock sendServer function that simulates successful HTTP responses\n */\nasync function mockSendServer(\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n): Promise<SendResponse> {\n // Simulate successful Meta API response\n return {\n ok: true,\n data: {\n events_received: 1,\n messages: [],\n fbtrace_id: 'mock-trace-id',\n },\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing Meta Conversions API events without making\n * actual HTTP requests to Facebook's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Meta Conversions API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body, options)`\n * where `url` is `${settings.url}/${settings.pixelId}/events`, `body` is the\n * JSON-stringified `{ data: [serverEvent] }` payload, and `options` carries the\n * access token in an `Authorization: Bearer` header (never in the URL).\n *\n * The public name users see when inspecting the destination is `sendServer`,\n * so each `out` tuple is `['sendServer', url, body, options]` with `body` as\n * the already-stringified JSON payload (mirroring the actual call signature).\n *\n * Functions in mappings are published as source code, so they must not use\n * imported helpers.\n *\n * The test fixture pins `accessToken = 's3cr3t'` and `pixelId = '1234567890'`,\n * so every endpoint resolves to:\n * https://graph.facebook.com/v22.0/1234567890/events\n * with header `Authorization: Bearer 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_id\n * 3. event_time (unix seconds; `Math.round(event.timestamp / 1000)`)\n * 4. action_source\n * 5. ...mapped event data (currency, value, etc.)\n * 6. user_data (hashed per Meta's PII requirements)\n * 7. event_source_url (appended after hash when action_source === 'website')\n */\nconst ENDPOINT = 'https://graph.facebook.com/v22.0/1234567890/events';\n\nconst OPTIONS = { headers: { Authorization: 'Bearer s3cr3t' } };\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is sent to the Meta Conversions API as a Purchase event with value, currency, and contents.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60001',\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n { entity: 'product', data: { id: 'SKU-A1', price: 129.99, quantity: 2 } },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n order_id: 'data.id',\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n typeof entity === 'object' &&\n entity !== null &&\n 'entity' in entity &&\n 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 num_items: {\n fn: (event: unknown) =>\n (event as WalkerOS.Event).nested.filter(\n (item) => item.entity === 'product',\n ).length,\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60001',\n event_time: 1700000900,\n action_source: 'website',\n order_id: 'ORD-300',\n currency: 'EUR',\n value: 249.99,\n contents: [{ id: 'SKU-A1', item_price: 129.99, quantity: 2 }],\n num_items: 1,\n user_data: {},\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Form submit',\n description:\n 'A form submission is forwarded to Meta CAPI as a custom event with the event source URL.',\n in: getEvent('form submit', {\n id: 'c1d2e3f4a5b60002',\n timestamp: 1700000901000,\n data: { type: 'newsletter' },\n user: { email: 'user@example.com' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com',\n },\n }),\n mapping: undefined,\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'form submit',\n event_id: 'c1d2e3f4a5b60002',\n event_time: 1700000901,\n action_source: 'website',\n user_data: {},\n event_source_url: 'https://example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n\nexport const purchaseWithClickAttribution: Flow.StepExample = {\n title: 'Purchase with fbclid',\n description:\n 'A purchase is sent to Meta CAPI with an external_id and a formatted fbc click id for ads attribution.',\n in: getEvent('order complete', {\n id: 'c1d2e3f4a5b60003',\n timestamp: 1700000902000,\n data: { id: 'ORD-700', total: 89.99, currency: 'USD' },\n user: { id: 'cust-42' },\n context: { fbclid: ['abc123xyz', 0] },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com',\n },\n }),\n mapping: {\n name: 'Purchase',\n data: {\n map: {\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n order_id: 'data.id',\n user_data: {\n map: {\n external_id: 'user.id',\n fbclid: 'context.fbclid.0',\n },\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n data: [\n {\n event_name: 'Purchase',\n event_id: 'c1d2e3f4a5b60003',\n event_time: 1700000902,\n action_source: 'website',\n currency: 'USD',\n value: 89.99,\n order_id: 'ORD-700',\n user_data: {\n // sha256('cust-42')\n external_id:\n '8a3c5a67cad508582b5edf6b8352cea3ffbad7f44812c1a736b4444c0f5746aa',\n // fb.subdomainIndex.creationTime.fbclid, creationTime in milliseconds\n fbc: 'fb.1.1700000902000.abc123xyz',\n },\n event_source_url: 'https://shop.example.com',\n },\n ],\n }),\n OPTIONS,\n ],\n ],\n};\n"],"mappings":"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","names":["z","z","z"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -11,6 +11,18 @@ interface Settings {
|
|
|
11
11
|
test_event_code?: string;
|
|
12
12
|
url?: string;
|
|
13
13
|
user_data?: UserDataMap;
|
|
14
|
+
/**
|
|
15
|
+
* Client IP, sent as user_data.client_ip_address. Resolves against
|
|
16
|
+
* { ingest, event }. `false` switches it off.
|
|
17
|
+
* @default ['ingest.ip', 'event.user.ip']
|
|
18
|
+
*/
|
|
19
|
+
ip?: Mapping$1.Value | false;
|
|
20
|
+
/**
|
|
21
|
+
* Client user agent, sent as user_data.client_user_agent. Resolves against
|
|
22
|
+
* { ingest, event }. `false` switches it off.
|
|
23
|
+
* @default ['ingest.userAgent', 'event.user.userAgent']
|
|
24
|
+
*/
|
|
25
|
+
userAgent?: Mapping$1.Value | false;
|
|
14
26
|
}
|
|
15
27
|
type UserDataKey = (typeof userDataKeys)[number];
|
|
16
28
|
/** Mapping of Meta customer information parameters to event values */
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ interface Settings {
|
|
|
11
11
|
test_event_code?: string;
|
|
12
12
|
url?: string;
|
|
13
13
|
user_data?: UserDataMap;
|
|
14
|
+
/**
|
|
15
|
+
* Client IP, sent as user_data.client_ip_address. Resolves against
|
|
16
|
+
* { ingest, event }. `false` switches it off.
|
|
17
|
+
* @default ['ingest.ip', 'event.user.ip']
|
|
18
|
+
*/
|
|
19
|
+
ip?: Mapping$1.Value | false;
|
|
20
|
+
/**
|
|
21
|
+
* Client user agent, sent as user_data.client_user_agent. Resolves against
|
|
22
|
+
* { ingest, event }. `false` switches it off.
|
|
23
|
+
* @default ['ingest.userAgent', 'event.user.userAgent']
|
|
24
|
+
*/
|
|
25
|
+
userAgent?: Mapping$1.Value | false;
|
|
14
26
|
}
|
|
15
27
|
type UserDataKey = (typeof userDataKeys)[number];
|
|
16
28
|
/** Mapping of Meta customer information parameters to event values */
|
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 name2 in all)__defProp(target,name2,{get:all[name2],enumerable:!0})})(index_exports,{DestinationMeta:()=>types_exports,default:()=>index_default,destinationMeta:()=>destinationMeta}),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_core2=require("@walkeros/core"),import_server_core2=require("@walkeros/server-core"),import_core=require("@walkeros/core"),import_server_core=require("@walkeros/server-core"),trimLower=value=>value.trim().toLowerCase(),lettersAndNumbers=value=>value.toLowerCase().replace(/[^\p{L}\p{N}]/gu,""),name=value=>value.toLowerCase().replace(/\p{P}/gu,"").trim(),normalizers={em:trimLower,ph:value=>value.replace(/\D/g,"").replace(/^0+/,""),fn:name,ln:name,db:value=>{const date=value.trim();return/^\d{4}\p{P}?\d{2}\p{P}?\d{2}$/u.test(date)?date.replace(/\D/g,""):date},ge:value=>trimLower(value).charAt(0),ct:lettersAndNumbers,st:lettersAndNumbers,zp:value=>{const zip=trimLower(value);return/^\d{5}[\s-]?\d{4}$/.test(zip)?zip.slice(0,5):zip.replace(/[\s-]/g,"")},country:trimLower,external_id:value=>value};function getNormalizer(key,doNotHash=[]){if(Object.hasOwn(normalizers,key)&&!doNotHash.includes(key))return normalizers[key]}function hashValue(key,value,normalize,logger){const normalized=normalize(String(value));return"db"!==key||/^\d{8}$/.test(normalized)||logger?.warn("Meta user_data db is not YYYYMMDD after normalization and cannot match"),(0,import_server_core.getHashServer)(normalized)}async function processValue(key,value,normalize,logger){return normalize?(0,import_core.isArray)(value)?Promise.all(value.map(item=>hashValue(key,item,normalize,logger))):hashValue(key,value,normalize,logger):value}var userDataKeys=["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"];var push=async function(event,{config:config,rule:rule,data:data,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="website",doNotHash:doNotHash,test_event_code:test_event_code,url:url="https://graph.facebook.com/v22.0/",user_data:user_data}=config.settings,eventData=(0,import_core2.isObject)(data)?data:{},configData=config.data?await(0,import_core2.getMappingValue)(event,config.data,{collector:collector}):{},userDataCustom=user_data?await(0,import_core2.getMappingValue)(event,{map:user_data},{collector:collector}):{},mappedUserData={...(0,import_core2.isObject)(configData)&&(0,import_core2.isObject)(configData.user_data)?configData.user_data:{},...(0,import_core2.isObject)(userDataCustom)?userDataCustom:{},...(0,import_core2.isObject)(eventData.user_data)?eventData.user_data:{}},unknownKeys=function(userData){const known=userDataKeys;return Object.keys(userData).filter(key=>!known.includes(key))}(mappedUserData);unknownKeys.length&&logger.warn("Unknown Meta user_data keys dropped, use parameter names such as em and ph",{keys:unknownKeys});const userData=Object.fromEntries(Object.entries(mappedUserData).filter(([key])=>!unknownKeys.includes(key)));userData.fbclid&&(userData.fbc=function(clickId,time){if(!clickId)return;const version="fb",subdomainIndex="1",creationTime=time||Date.now();return`${version}.${subdomainIndex}.${creationTime}.${clickId}`}(userData.fbclid,collector?.session?.start||event.timestamp),delete userData.fbclid);const serverEvent={event_name:event.name,event_id:event.id,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,...eventData,user_data:userData};"website"===action_source&&event.source?.url&&(serverEvent.event_source_url=event.source.url);const hashedServerEvent=await async function(value,doNotHash=[],logger){if(!(0,import_core.isObject)(value))return value;const isUserData="user_data"in value,target=isUserData?value.user_data:value,result=(await Promise.all(Object.entries(target).map(async([k,v])=>[k,await processValue(k,v,isUserData?getNormalizer(k,doNotHash):void 0,logger)]))).reduce((acc,[k,v])=>((0,import_core.isString)(k)&&(acc[k]=v),acc),{});return isUserData?{...value,user_data:result}:result}(serverEvent,doNotHash,logger),body={data:[hashedServerEvent]};test_event_code&&(body.test_event_code=test_event_code);const endpoint=`${url.replace(/\/+$/,"")}/${pixelId}/events`;logger.debug("Calling Meta API",{endpoint:endpoint,method:"POST",eventName:serverEvent.event_name,eventId:serverEvent.event_id});const sendServerFn=env?.sendServer||import_server_core2.sendServer,result=await sendServerFn(endpoint,JSON.stringify(body),{headers:{Authorization:`Bearer ${accessToken}`}});logger.debug("Meta API response",{ok:!(0,import_core2.isObject)(result)||result.ok}),(0,import_core2.isObject)(result)&&!1===result.ok&&logger.throw(`Meta API error: ${JSON.stringify(result)}`)};var types_exports={},destinationMeta={type:"meta",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={...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationMeta;//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name2 in all)__defProp(target,name2,{get:all[name2],enumerable:!0})})(index_exports,{DestinationMeta:()=>types_exports,default:()=>index_default,destinationMeta:()=>destinationMeta}),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_core2=require("@walkeros/core"),import_server_core2=require("@walkeros/server-core"),import_core=require("@walkeros/core"),import_server_core=require("@walkeros/server-core"),trimLower=value=>value.trim().toLowerCase(),lettersAndNumbers=value=>value.toLowerCase().replace(/[^\p{L}\p{N}]/gu,""),name=value=>value.toLowerCase().replace(/\p{P}/gu,"").trim(),normalizers={em:trimLower,ph:value=>value.replace(/\D/g,"").replace(/^0+/,""),fn:name,ln:name,db:value=>{const date=value.trim();return/^\d{4}\p{P}?\d{2}\p{P}?\d{2}$/u.test(date)?date.replace(/\D/g,""):date},ge:value=>trimLower(value).charAt(0),ct:lettersAndNumbers,st:lettersAndNumbers,zp:value=>{const zip=trimLower(value);return/^\d{5}[\s-]?\d{4}$/.test(zip)?zip.slice(0,5):zip.replace(/[\s-]/g,"")},country:trimLower,external_id:value=>value};function getNormalizer(key,doNotHash=[]){if(Object.hasOwn(normalizers,key)&&!doNotHash.includes(key))return normalizers[key]}function hashValue(key,value,normalize,logger){const normalized=normalize(String(value));return"db"!==key||/^\d{8}$/.test(normalized)||logger?.warn("Meta user_data db is not YYYYMMDD after normalization and cannot match"),(0,import_server_core.getHashServer)(normalized)}async function processValue(key,value,normalize,logger){return normalize?(0,import_core.isArray)(value)?Promise.all(value.map(item=>hashValue(key,item,normalize,logger))):hashValue(key,value,normalize,logger):value}var userDataKeys=["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"];var push=async function(event,{config:config,rule:rule,data:data,ingest:ingest,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="website",doNotHash:doNotHash,test_event_code:test_event_code,url:url="https://graph.facebook.com/v22.0/",user_data:user_data,ip:ip,userAgent:userAgent}=config.settings,eventData=(0,import_core2.isObject)(data)?data:{},configData=config.data?await(0,import_core2.getMappingValue)(event,config.data,{collector:collector}):{},userDataCustom=user_data?await(0,import_core2.getMappingValue)(event,{map:user_data},{collector:collector}):{},root=(0,import_core2.createMappingRoot)(ingest,event),clientIp=await resolveClient(ip,DEFAULT_IP,root,collector),clientUserAgent=await resolveClient(userAgent,DEFAULT_USER_AGENT,root,collector),mappedUserData={...void 0!==clientIp?{client_ip_address:clientIp}:{},...void 0!==clientUserAgent?{client_user_agent:clientUserAgent}:{},...(0,import_core2.isObject)(configData)&&(0,import_core2.isObject)(configData.user_data)?configData.user_data:{},...(0,import_core2.isObject)(userDataCustom)?userDataCustom:{},...(0,import_core2.isObject)(eventData.user_data)?eventData.user_data:{}},unknownKeys=function(userData){const known=userDataKeys;return Object.keys(userData).filter(key=>!known.includes(key))}(mappedUserData);unknownKeys.length&&logger.warn("Unknown Meta user_data keys dropped, use parameter names such as em and ph",{keys:unknownKeys});const userData=Object.fromEntries(Object.entries(mappedUserData).filter(([key])=>!unknownKeys.includes(key)));userData.fbclid&&(userData.fbc=function(clickId,time){if(!clickId)return;const version="fb",subdomainIndex="1",creationTime=time||Date.now();return`${version}.${subdomainIndex}.${creationTime}.${clickId}`}(userData.fbclid,collector?.session?.start||event.timestamp),delete userData.fbclid);const serverEvent={event_name:event.name,event_id:event.id,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,...eventData,user_data:userData};"website"===action_source&&event.source?.url&&(serverEvent.event_source_url=event.source.url);const hashedServerEvent=await async function(value,doNotHash=[],logger){if(!(0,import_core.isObject)(value))return value;const isUserData="user_data"in value,target=isUserData?value.user_data:value,result=(await Promise.all(Object.entries(target).map(async([k,v])=>[k,await processValue(k,v,isUserData?getNormalizer(k,doNotHash):void 0,logger)]))).reduce((acc,[k,v])=>((0,import_core.isString)(k)&&(acc[k]=v),acc),{});return isUserData?{...value,user_data:result}:result}(serverEvent,doNotHash,logger),body={data:[hashedServerEvent]};test_event_code&&(body.test_event_code=test_event_code);const endpoint=`${url.replace(/\/+$/,"")}/${pixelId}/events`;logger.debug("Calling Meta API",{endpoint:endpoint,method:"POST",eventName:serverEvent.event_name,eventId:serverEvent.event_id});const sendServerFn=env?.sendServer||import_server_core2.sendServer,result=await sendServerFn(endpoint,JSON.stringify(body),{headers:{Authorization:`Bearer ${accessToken}`}});logger.debug("Meta API response",{ok:!(0,import_core2.isObject)(result)||result.ok}),(0,import_core2.isObject)(result)&&!1===result.ok&&logger.throw(`Meta API error: ${JSON.stringify(result)}`)},DEFAULT_IP=["ingest.ip","event.user.ip"],DEFAULT_USER_AGENT=["ingest.userAgent","event.user.userAgent"];async function resolveClient(setting,fallback,root,collector){if(!1===setting)return;const value=await(0,import_core2.getMappingValue)(root,setting??fallback,{collector:collector});return"string"==typeof value&&""!==value?value:void 0}var types_exports={},destinationMeta={type:"meta",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={...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationMeta;//# 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/userData.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMeta from './types';\n\nexport const destinationMeta: Destination = {\n type: 'meta',\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 destinationMeta;\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 ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n BodyParameters,\n CustomerInformationParameters,\n PushFn,\n ServerEventParameters,\n Env,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashEvent } from './hash';\nimport { getUnknownUserDataKeys } from './userData';\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 = 'website',\n doNotHash,\n test_event_code,\n url = 'https://graph.facebook.com/v22.0/',\n user_data,\n } = config.settings!;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data, { collector })\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n\n const mappedUserData = {\n // Destination config\n ...(isObject(configData) && isObject(configData.user_data)\n ? configData.user_data\n : {}),\n // Custom user_data\n ...(isObject(userDataCustom) ? userDataCustom : {}),\n // Event mapping\n ...(isObject(eventData.user_data) ? eventData.user_data : {}),\n };\n\n // Unknown keys are never hashed, so drop them instead of sending cleartext\n const unknownKeys = getUnknownUserDataKeys(mappedUserData);\n if (unknownKeys.length)\n logger.warn(\n 'Unknown Meta user_data keys dropped, use parameter names such as em and ph',\n { keys: unknownKeys },\n );\n\n const userData: CustomerInformationParameters = Object.fromEntries(\n Object.entries(mappedUserData).filter(\n ([key]) => !unknownKeys.includes(key),\n ),\n );\n\n if (userData.fbclid) {\n userData.fbc = formatClickId(\n userData.fbclid,\n collector?.session?.start || event.timestamp,\n );\n delete userData.fbclid;\n }\n const serverEvent: ServerEventParameters = {\n event_name: event.name,\n event_id: event.id,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n ...eventData,\n user_data: userData,\n };\n\n if (action_source === 'website' && event.source?.url)\n serverEvent.event_source_url = event.source.url;\n\n const hashedServerEvent = await hashEvent(serverEvent, doNotHash, logger);\n\n const body: BodyParameters = { data: [hashedServerEvent] };\n\n // Test event code\n if (test_event_code) body.test_event_code = test_event_code;\n\n const endpoint = `${url.replace(/\\/+$/, '')}/${pixelId}/events`;\n logger.debug('Calling Meta API', {\n endpoint,\n method: 'POST',\n eventName: serverEvent.event_name,\n eventId: serverEvent.event_id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n logger.debug('Meta API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Meta API error: ${JSON.stringify(result)}`);\n }\n};\n\nfunction formatClickId(clickId: unknown, time?: number): string | undefined {\n // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#2--format-clickid\n\n if (!clickId) return;\n\n // Version is always \"fb\"\n const version = 'fb';\n\n // Subdomain ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)\n const subdomainIndex = '1';\n\n // Get the current timestamp in milliseconds (or when the fbclid was observed)\n const creationTime = time || Date.now();\n\n return `${version}.${subdomainIndex}.${creationTime}.${clickId}`;\n}\n","import type { Logger, WalkerOS } from '@walkeros/core';\nimport { isArray, isObject, isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\ntype Normalizer = (value: string) => string;\n\nconst trimLower: Normalizer = (value) => value.trim().toLowerCase();\n\nconst lettersAndNumbers: Normalizer = (value) =>\n value.toLowerCase().replace(/[^\\p{L}\\p{N}]/gu, '');\n\nconst name: Normalizer = (value) =>\n value.toLowerCase().replace(/\\p{P}/gu, '').trim();\n\n// Formatting rules per key, applied before hashing:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nconst normalizers: Record<string, Normalizer> = {\n em: trimLower,\n ph: (value) => value.replace(/\\D/g, '').replace(/^0+/, ''),\n fn: name,\n ln: name,\n db: (value) => {\n const date = value.trim();\n return /^\\d{4}\\p{P}?\\d{2}\\p{P}?\\d{2}$/u.test(date)\n ? date.replace(/\\D/g, '')\n : date;\n },\n ge: (value) => trimLower(value).charAt(0),\n ct: lettersAndNumbers,\n st: lettersAndNumbers,\n zp: (value) => {\n const zip = trimLower(value);\n if (/^\\d{5}[\\s-]?\\d{4}$/.test(zip)) return zip.slice(0, 5);\n return zip.replace(/[\\s-]/g, '');\n },\n country: trimLower,\n external_id: (value) => value,\n};\n\n// Keys listed in doNotHash are sent exactly as mapped, without normalization\nfunction getNormalizer(\n key: string,\n doNotHash: string[] = [],\n): Normalizer | undefined {\n if (!Object.hasOwn(normalizers, key) || doNotHash.includes(key)) return;\n return normalizers[key];\n}\n\nfunction hashValue(\n key: string,\n value: unknown,\n normalize: Normalizer,\n logger?: Logger.Instance,\n): Promise<string> {\n const normalized = normalize(String(value));\n if (key === 'db' && !/^\\d{8}$/.test(normalized))\n logger?.warn(\n 'Meta user_data db is not YYYYMMDD after normalization and cannot match',\n );\n return getHashServer(normalized);\n}\n\ntype HashableValue = WalkerOS.AnyObject | unknown | unknown[];\n\nasync function processValue(\n key: string,\n value: unknown,\n normalize?: Normalizer,\n logger?: Logger.Instance,\n): Promise<unknown> {\n if (!normalize) return value;\n if (isArray(value)) {\n return Promise.all(\n value.map((item) => hashValue(key, item, normalize, logger)),\n );\n }\n return hashValue(key, value, normalize, logger);\n}\n\nexport async function hashEvent<T extends HashableValue>(\n value: T,\n doNotHash: string[] = [],\n logger?: Logger.Instance,\n): Promise<T> {\n if (!isObject(value)) return value;\n\n const isUserData = 'user_data' in value;\n const target = (isUserData ? value.user_data : value) as WalkerOS.AnyObject;\n\n const entries = await Promise.all(\n Object.entries(target).map(async ([k, v]) => [\n k,\n await processValue(\n k,\n v,\n isUserData ? getNormalizer(k, doNotHash) : undefined,\n logger,\n ),\n ]),\n );\n\n const result = entries.reduce((acc, [k, v]) => {\n if (isString(k)) acc[k] = v;\n return acc;\n }, {} as WalkerOS.AnyObject);\n\n return isUserData ? { ...value, user_data: result } : (result as T);\n}\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\nimport type { userDataKeys } from '../userData';\n\nexport interface Settings {\n accessToken: string;\n pixelId: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n test_event_code?: string;\n url?: string;\n user_data?: UserDataMap;\n}\n\nexport type UserDataKey = (typeof userDataKeys)[number];\n\n/** Mapping of Meta customer information parameters to event values */\nexport type UserDataMap = Partial<Record<UserDataKey, WalkerOSMapping.Value>>;\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// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/main-body\nexport interface BodyParameters {\n data: Array<ServerEventParameters>;\n test_event_code?: string;\n}\n\n/**\n * Represents the top‑level parameters for a server event sent via Meta's Conversions API.\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport interface ServerEventParameters extends StandardParameters {\n /** The event name or custom event identifier. Required for deduplication. */\n event_name: EventName;\n\n /** Unix timestamp (in seconds) when the event actually occurred. GMT timezone. */\n event_time: number;\n\n /** Map of customer information for matching (emails, phone, etc.). */\n user_data: CustomerInformationParameters;\n\n /** Additional business data about the event. */\n custom_data?: Record<string, unknown>;\n\n /** URL of the page where the event occurred. */\n event_source_url?: string;\n\n /** If true, exclude this event from ads optimization (only attribution). */\n opt_out?: boolean;\n\n /** Unique ID for deduplication across Pixel and CAPI. */\n event_id?: string;\n\n /** Source of the event (e.g., website, app). */\n action_source: ActionSource;\n\n /** Processing options (e.g., ['LDU'] for CCPA limited data use). */\n data_processing_options?: DataProcessingOption[];\n\n /** Country code for data processing option (1 = USA, 0 = auto‑geolocate). */\n data_processing_options_country?: number;\n\n /** State code for data processing option (1000 = California, 0 = auto). */\n data_processing_options_state?: number;\n\n /** App‑specific data (required if action_source is 'app'). */\n app_data?: AppData;\n\n /** HTTP referrer header of the event. */\n referrer_url?: string;\n\n /** Metadata to link delayed events to past acquisition events. */\n original_event_data?: OriginalEventDataParameters;\n\n /** User segment for more context about the customer's relationship. */\n customer_segmentation?: CustomerSegmentation;\n}\n\nexport type EventName =\n | 'AddPaymentInfo'\n | 'AddToCart'\n | 'AddToWishlist'\n | 'CompleteRegistration'\n | 'Contact'\n | 'CustomizeProduct'\n | 'Donate'\n | 'FindLocation'\n | 'InitiateCheckout'\n | 'Lead'\n | 'Purchase'\n | 'Schedule'\n | 'Search'\n | 'StartTrial'\n | 'SubmitApplication'\n | 'Subscribe'\n | 'ViewContent'\n | string;\n\nexport type ActionSource =\n | 'email'\n | 'website'\n | 'app'\n | 'phone_call'\n | 'chat'\n | 'physical_store'\n | 'system_generated'\n | 'business_messaging'\n | 'other';\n\nexport type DataProcessingOption = 'LDU';\n\nexport type CustomerSegmentation =\n | 'new_customer_to_business'\n | 'new_customer_to_business_line'\n | 'new_customer_to_product_area'\n | 'new_customer_to_medium'\n | 'existing_customer_to_business'\n | 'existing_customer_to_business_line'\n | 'existing_customer_to_product_area'\n | 'existing_customer_to_medium'\n | 'customer_in_loyalty_program';\n\n/** Extended device info for app events (Android version 'a2', iOS 'i2') */\nexport interface AppData {\n /**\n * Comma-separated array of strings with fixed order:\n * [sdk_version, os_version, device_model, device_brand,\n * screen_width, screen_height, ...]\n */\n extinfo: string[];\n}\n\n// Customer Information Parameters\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nexport interface CustomerInformationParameters {\n /** Email(s), SHA-256 hashed, lowercase and trimmed */\n em?: string | string[];\n\n /** Phone number(s), SHA-256 hashed, E.164 format (no leading 0s or symbols) */\n ph?: string | string[];\n\n /** First name(s), SHA-256 hashed, lowercase */\n fn?: string | string[];\n\n /** Last name(s), SHA-256 hashed, lowercase */\n ln?: string | string[];\n\n /** Date(s) of birth in YYYYMMDD, SHA-256 hashed */\n db?: string | string[];\n\n /** Gender(s) in lowercase single letter (\"m\", \"f\", etc.), SHA-256 hashed */\n ge?: string | string[];\n\n /** City name(s), SHA-256 hashed, lowercase */\n ct?: string | string[];\n\n /** State abbreviation(s), SHA-256 hashed, lowercase (e.g., \"ca\", \"ny\") */\n st?: string | string[];\n\n /** ZIP or postal code(s), SHA-256 hashed, lowercase */\n zp?: string | string[];\n\n /** Country code(s), SHA-256 hashed, lowercase (ISO 3166-1 alpha-2) */\n country?: string | string[];\n\n /** External IDs, unique per user. SHA-256 hash recommended */\n external_id?: string | string[];\n\n /** IPv4 or IPv6 address of client. Do NOT hash. */\n client_ip_address?: string;\n\n /** User agent string from browser. Do NOT hash. */\n client_user_agent?: string;\n\n /** fbclid parameter value from the URL. Do NOT hash. */\n fbclid?: string;\n\n /** Facebook click ID (_fbc cookie). Do NOT hash. */\n fbc?: string;\n\n /** Facebook browser ID (_fbp cookie). Do NOT hash. */\n fbp?: string;\n\n /** Subscription ID for the transaction. Do NOT hash. */\n subscription_id?: string;\n\n /** Facebook login ID (App-Scoped ID). Do NOT hash. */\n fb_login_id?: number;\n\n /** Meta Lead Ad lead ID. Do NOT hash. */\n lead_id?: number;\n\n /** Anonymous install ID. App events only. Do NOT hash. */\n anon_id?: string;\n\n /** Mobile advertiser ID (GAID/IDFA). Do NOT hash. */\n madid?: string;\n\n /** Facebook Page ID. Do NOT hash. */\n page_id?: string;\n\n /** Messenger Page-scoped user ID. Do NOT hash. */\n page_scoped_user_id?: string;\n\n /** Click to WhatsApp ad click ID. Do NOT hash. */\n ctwa_clid?: string;\n\n /** Instagram business account ID. Do NOT hash. */\n ig_account_id?: string;\n\n /** Instagram-scoped user ID. Do NOT hash. */\n ig_sid?: string;\n}\n\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/custom-data\nexport interface StandardParameters {\n // Web and Offline parameters\n availability?: string;\n body_style?: string;\n checkin_date?: string;\n city?: string;\n condition_of_vehicle?: string;\n content_ids?: string[];\n content_type?: 'product' | 'product_group' | string;\n contents?: Array<{\n id: string;\n quantity?: number;\n item_price?: number;\n delivery_category?: string;\n }>;\n country?: string;\n currency?: string;\n delivery_category?: 'in_store' | 'curbside' | 'home_delivery' | string;\n departing_arrival_date?: string;\n departing_departure_date?: string;\n destination_airport?: string;\n destination_ids?: string[];\n dma_code?: string;\n drivetrain?: string;\n exterior_color?: string;\n fuel_type?: string;\n hotel_score?: number;\n interior_color?: string;\n lead_event_source?: string;\n lease_end_date?: string;\n lease_start_date?: string;\n listing_type?: string;\n make?: string;\n // @TODO is mileage an object?\n 'mileage.unit'?: string;\n 'mileage.value'?: number;\n model?: string;\n neighborhood?: string;\n net_revenue?: number;\n num_adults?: number;\n num_children?: number;\n num_infants?: number;\n num_items?: number;\n order_id?: string;\n origin_airport?: string;\n postal_code?: string;\n predicted_ltv?: number;\n preferred_baths_range?: string;\n preferred_beds_range?: string;\n preferred_neighborhoods?: string[];\n preferred_num_stops?: number;\n preferred_price_range?: string;\n preferred_star_ratings?: [number, number];\n price?: string;\n product_catalog_id?: string;\n property_type?: string;\n region?: string;\n returning_arrival_date?: string;\n returning_departure_date?: string;\n search_string?: string;\n state_of_vehicle?: string;\n suggested_destinations?: string[];\n suggested_home_listings?: string[];\n suggested_hotels?: string[];\n suggested_jobs?: string[];\n suggested_local_service_businesses?: string[];\n suggested_location_based_items?: string[];\n suggested_vehicles?: string[];\n transmission?: string;\n travel_class?: string;\n travel_end?: string;\n travel_start?: string;\n trim?: string;\n\n // App-specific parameters (with fb_ prefix)\n fb_availability?: string;\n fb_body_style?: string;\n fb_checkin_date?: string;\n fb_city?: string;\n fb_condition_of_vehicle?: string;\n fb_content_ids?: string[];\n fb_content_type?: string;\n fb_contents?: Array<{ id: string; quantity?: number; item_price?: number }>;\n fb_country?: string;\n fb_currency?: string;\n fb_delivery_category?: string;\n fb_departing_arrival_date?: string;\n fb_departing_departure_date?: string;\n fb_destination_airport?: string;\n fb_destination_ids?: string[];\n fb_dma_code?: string;\n fb_drivetrain?: string;\n fb_exterior_color?: string;\n fb_fuel_type?: string;\n fb_hotel_score?: number;\n fb_interior_color?: string;\n fb_lease_end_date?: string;\n fb_lease_start_date?: string;\n fb_listing_type?: string;\n fb_make?: string;\n // @TODO is fb_mileage an object?\n 'fb_mileage.unit'?: string;\n 'fb_mileage.value'?: number;\n fb_model?: string;\n fb_neighborhood?: string;\n fb_num_adults?: number;\n fb_num_children?: number;\n fb_num_infants?: number;\n fb_num_items?: number;\n fb_order_id?: string;\n fb_origin_airport?: string;\n fb_postal_code?: string;\n fb_predicted_ltv?: number;\n fb_preferred_baths_range?: string;\n fb_preferred_beds_range?: string;\n fb_preferred_neighborhoods?: string[];\n fb_preferred_num_stops?: number;\n fb_preferred_price_range?: string;\n fb_preferred_star_ratings?: [number, number];\n fb_price?: string;\n fb_product_catalog_id?: string;\n fb_property_type?: string;\n fb_region?: string;\n fb_returning_arrival_date?: string;\n fb_returning_departure_date?: string;\n fb_search_string?: string;\n fb_state_of_vehicle?: string;\n fb_suggested_destinations?: string[];\n fb_suggested_home_listings?: string[];\n fb_suggested_hotels?: string[];\n fb_suggested_jobs?: string[];\n fb_suggested_local_service_businesses?: string[];\n fb_suggested_location_based_items?: string[];\n fb_suggested_vehicles?: string[];\n fb_transmission?: string;\n fb_travel_class?: string;\n fb_travel_end?: string;\n fb_travel_start?: string;\n\n // Offline-specific parameters\n user_bucket?: string;\n value?: number;\n vin?: string;\n year?: number;\n item_number?: string;\n}\n\nexport interface OriginalEventDataParameters {\n event_name?: EventName;\n event_time?: number;\n order_id?: number;\n event_id?: string;\n}\n"],"mappings":"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","names":["import_core","import_server_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/hash.ts","../src/userData.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMeta from './types';\n\nexport const destinationMeta: Destination = {\n type: 'meta',\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 destinationMeta;\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 ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n BodyParameters,\n CustomerInformationParameters,\n PushFn,\n ServerEventParameters,\n Env,\n} from './types';\nimport type { Collector, Mapping as WalkerOSMapping } from '@walkeros/core';\nimport { createMappingRoot, getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashEvent } from './hash';\nimport { getUnknownUserDataKeys } from './userData';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, ingest, collector, env, logger },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'website',\n doNotHash,\n test_event_code,\n url = 'https://graph.facebook.com/v22.0/',\n user_data,\n ip,\n userAgent,\n } = config.settings!;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data, { collector })\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n\n // Client IP and user agent auto-fill, overridden by any mapped value\n const root = createMappingRoot(ingest, event);\n const clientIp = await resolveClient(ip, DEFAULT_IP, root, collector);\n const clientUserAgent = await resolveClient(\n userAgent,\n DEFAULT_USER_AGENT,\n root,\n collector,\n );\n\n const mappedUserData = {\n ...(clientIp !== undefined ? { client_ip_address: clientIp } : {}),\n ...(clientUserAgent !== undefined\n ? { client_user_agent: clientUserAgent }\n : {}),\n // Destination config\n ...(isObject(configData) && isObject(configData.user_data)\n ? configData.user_data\n : {}),\n // Custom user_data\n ...(isObject(userDataCustom) ? userDataCustom : {}),\n // Event mapping\n ...(isObject(eventData.user_data) ? eventData.user_data : {}),\n };\n\n // Unknown keys are never hashed, so drop them instead of sending cleartext\n const unknownKeys = getUnknownUserDataKeys(mappedUserData);\n if (unknownKeys.length)\n logger.warn(\n 'Unknown Meta user_data keys dropped, use parameter names such as em and ph',\n { keys: unknownKeys },\n );\n\n const userData: CustomerInformationParameters = Object.fromEntries(\n Object.entries(mappedUserData).filter(\n ([key]) => !unknownKeys.includes(key),\n ),\n );\n\n if (userData.fbclid) {\n userData.fbc = formatClickId(\n userData.fbclid,\n collector?.session?.start || event.timestamp,\n );\n delete userData.fbclid;\n }\n const serverEvent: ServerEventParameters = {\n event_name: event.name,\n event_id: event.id,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n ...eventData,\n user_data: userData,\n };\n\n if (action_source === 'website' && event.source?.url)\n serverEvent.event_source_url = event.source.url;\n\n const hashedServerEvent = await hashEvent(serverEvent, doNotHash, logger);\n\n const body: BodyParameters = { data: [hashedServerEvent] };\n\n // Test event code\n if (test_event_code) body.test_event_code = test_event_code;\n\n const endpoint = `${url.replace(/\\/+$/, '')}/${pixelId}/events`;\n logger.debug('Calling Meta API', {\n endpoint,\n method: 'POST',\n eventName: serverEvent.event_name,\n eventId: serverEvent.event_id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n logger.debug('Meta API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Meta API error: ${JSON.stringify(result)}`);\n }\n};\n\nconst DEFAULT_IP: WalkerOSMapping.Value = ['ingest.ip', 'event.user.ip'];\nconst DEFAULT_USER_AGENT: WalkerOSMapping.Value = [\n 'ingest.userAgent',\n 'event.user.userAgent',\n];\n\n/** A client IP or user agent setting resolved to a non-empty string. */\nasync function resolveClient(\n setting: WalkerOSMapping.Value | false | undefined,\n fallback: WalkerOSMapping.Value,\n root: WalkerOSMapping.Root,\n collector: Collector.Instance,\n): Promise<string | undefined> {\n if (setting === false) return undefined;\n const value = await getMappingValue(root, setting ?? fallback, { collector });\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction formatClickId(clickId: unknown, time?: number): string | undefined {\n // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#2--format-clickid\n\n if (!clickId) return;\n\n // Version is always \"fb\"\n const version = 'fb';\n\n // Subdomain ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)\n const subdomainIndex = '1';\n\n // Get the current timestamp in milliseconds (or when the fbclid was observed)\n const creationTime = time || Date.now();\n\n return `${version}.${subdomainIndex}.${creationTime}.${clickId}`;\n}\n","import type { Logger, WalkerOS } from '@walkeros/core';\nimport { isArray, isObject, isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\ntype Normalizer = (value: string) => string;\n\nconst trimLower: Normalizer = (value) => value.trim().toLowerCase();\n\nconst lettersAndNumbers: Normalizer = (value) =>\n value.toLowerCase().replace(/[^\\p{L}\\p{N}]/gu, '');\n\nconst name: Normalizer = (value) =>\n value.toLowerCase().replace(/\\p{P}/gu, '').trim();\n\n// Formatting rules per key, applied before hashing:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nconst normalizers: Record<string, Normalizer> = {\n em: trimLower,\n ph: (value) => value.replace(/\\D/g, '').replace(/^0+/, ''),\n fn: name,\n ln: name,\n db: (value) => {\n const date = value.trim();\n return /^\\d{4}\\p{P}?\\d{2}\\p{P}?\\d{2}$/u.test(date)\n ? date.replace(/\\D/g, '')\n : date;\n },\n ge: (value) => trimLower(value).charAt(0),\n ct: lettersAndNumbers,\n st: lettersAndNumbers,\n zp: (value) => {\n const zip = trimLower(value);\n if (/^\\d{5}[\\s-]?\\d{4}$/.test(zip)) return zip.slice(0, 5);\n return zip.replace(/[\\s-]/g, '');\n },\n country: trimLower,\n external_id: (value) => value,\n};\n\n// Keys listed in doNotHash are sent exactly as mapped, without normalization\nfunction getNormalizer(\n key: string,\n doNotHash: string[] = [],\n): Normalizer | undefined {\n if (!Object.hasOwn(normalizers, key) || doNotHash.includes(key)) return;\n return normalizers[key];\n}\n\nfunction hashValue(\n key: string,\n value: unknown,\n normalize: Normalizer,\n logger?: Logger.Instance,\n): Promise<string> {\n const normalized = normalize(String(value));\n if (key === 'db' && !/^\\d{8}$/.test(normalized))\n logger?.warn(\n 'Meta user_data db is not YYYYMMDD after normalization and cannot match',\n );\n return getHashServer(normalized);\n}\n\ntype HashableValue = WalkerOS.AnyObject | unknown | unknown[];\n\nasync function processValue(\n key: string,\n value: unknown,\n normalize?: Normalizer,\n logger?: Logger.Instance,\n): Promise<unknown> {\n if (!normalize) return value;\n if (isArray(value)) {\n return Promise.all(\n value.map((item) => hashValue(key, item, normalize, logger)),\n );\n }\n return hashValue(key, value, normalize, logger);\n}\n\nexport async function hashEvent<T extends HashableValue>(\n value: T,\n doNotHash: string[] = [],\n logger?: Logger.Instance,\n): Promise<T> {\n if (!isObject(value)) return value;\n\n const isUserData = 'user_data' in value;\n const target = (isUserData ? value.user_data : value) as WalkerOS.AnyObject;\n\n const entries = await Promise.all(\n Object.entries(target).map(async ([k, v]) => [\n k,\n await processValue(\n k,\n v,\n isUserData ? getNormalizer(k, doNotHash) : undefined,\n logger,\n ),\n ]),\n );\n\n const result = entries.reduce((acc, [k, v]) => {\n if (isString(k)) acc[k] = v;\n return acc;\n }, {} as WalkerOS.AnyObject);\n\n return isUserData ? { ...value, user_data: result } : (result as T);\n}\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\nimport type { userDataKeys } from '../userData';\n\nexport interface Settings {\n accessToken: string;\n pixelId: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n test_event_code?: string;\n url?: string;\n user_data?: UserDataMap;\n /**\n * Client IP, sent as user_data.client_ip_address. Resolves against\n * { ingest, event }. `false` switches it off.\n * @default ['ingest.ip', 'event.user.ip']\n */\n ip?: WalkerOSMapping.Value | false;\n /**\n * Client user agent, sent as user_data.client_user_agent. Resolves against\n * { ingest, event }. `false` switches it off.\n * @default ['ingest.userAgent', 'event.user.userAgent']\n */\n userAgent?: WalkerOSMapping.Value | false;\n}\n\nexport type UserDataKey = (typeof userDataKeys)[number];\n\n/** Mapping of Meta customer information parameters to event values */\nexport type UserDataMap = Partial<Record<UserDataKey, WalkerOSMapping.Value>>;\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// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/main-body\nexport interface BodyParameters {\n data: Array<ServerEventParameters>;\n test_event_code?: string;\n}\n\n/**\n * Represents the top‑level parameters for a server event sent via Meta's Conversions API.\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport interface ServerEventParameters extends StandardParameters {\n /** The event name or custom event identifier. Required for deduplication. */\n event_name: EventName;\n\n /** Unix timestamp (in seconds) when the event actually occurred. GMT timezone. */\n event_time: number;\n\n /** Map of customer information for matching (emails, phone, etc.). */\n user_data: CustomerInformationParameters;\n\n /** Additional business data about the event. */\n custom_data?: Record<string, unknown>;\n\n /** URL of the page where the event occurred. */\n event_source_url?: string;\n\n /** If true, exclude this event from ads optimization (only attribution). */\n opt_out?: boolean;\n\n /** Unique ID for deduplication across Pixel and CAPI. */\n event_id?: string;\n\n /** Source of the event (e.g., website, app). */\n action_source: ActionSource;\n\n /** Processing options (e.g., ['LDU'] for CCPA limited data use). */\n data_processing_options?: DataProcessingOption[];\n\n /** Country code for data processing option (1 = USA, 0 = auto‑geolocate). */\n data_processing_options_country?: number;\n\n /** State code for data processing option (1000 = California, 0 = auto). */\n data_processing_options_state?: number;\n\n /** App‑specific data (required if action_source is 'app'). */\n app_data?: AppData;\n\n /** HTTP referrer header of the event. */\n referrer_url?: string;\n\n /** Metadata to link delayed events to past acquisition events. */\n original_event_data?: OriginalEventDataParameters;\n\n /** User segment for more context about the customer's relationship. */\n customer_segmentation?: CustomerSegmentation;\n}\n\nexport type EventName =\n | 'AddPaymentInfo'\n | 'AddToCart'\n | 'AddToWishlist'\n | 'CompleteRegistration'\n | 'Contact'\n | 'CustomizeProduct'\n | 'Donate'\n | 'FindLocation'\n | 'InitiateCheckout'\n | 'Lead'\n | 'Purchase'\n | 'Schedule'\n | 'Search'\n | 'StartTrial'\n | 'SubmitApplication'\n | 'Subscribe'\n | 'ViewContent'\n | string;\n\nexport type ActionSource =\n | 'email'\n | 'website'\n | 'app'\n | 'phone_call'\n | 'chat'\n | 'physical_store'\n | 'system_generated'\n | 'business_messaging'\n | 'other';\n\nexport type DataProcessingOption = 'LDU';\n\nexport type CustomerSegmentation =\n | 'new_customer_to_business'\n | 'new_customer_to_business_line'\n | 'new_customer_to_product_area'\n | 'new_customer_to_medium'\n | 'existing_customer_to_business'\n | 'existing_customer_to_business_line'\n | 'existing_customer_to_product_area'\n | 'existing_customer_to_medium'\n | 'customer_in_loyalty_program';\n\n/** Extended device info for app events (Android version 'a2', iOS 'i2') */\nexport interface AppData {\n /**\n * Comma-separated array of strings with fixed order:\n * [sdk_version, os_version, device_model, device_brand,\n * screen_width, screen_height, ...]\n */\n extinfo: string[];\n}\n\n// Customer Information Parameters\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nexport interface CustomerInformationParameters {\n /** Email(s), SHA-256 hashed, lowercase and trimmed */\n em?: string | string[];\n\n /** Phone number(s), SHA-256 hashed, E.164 format (no leading 0s or symbols) */\n ph?: string | string[];\n\n /** First name(s), SHA-256 hashed, lowercase */\n fn?: string | string[];\n\n /** Last name(s), SHA-256 hashed, lowercase */\n ln?: string | string[];\n\n /** Date(s) of birth in YYYYMMDD, SHA-256 hashed */\n db?: string | string[];\n\n /** Gender(s) in lowercase single letter (\"m\", \"f\", etc.), SHA-256 hashed */\n ge?: string | string[];\n\n /** City name(s), SHA-256 hashed, lowercase */\n ct?: string | string[];\n\n /** State abbreviation(s), SHA-256 hashed, lowercase (e.g., \"ca\", \"ny\") */\n st?: string | string[];\n\n /** ZIP or postal code(s), SHA-256 hashed, lowercase */\n zp?: string | string[];\n\n /** Country code(s), SHA-256 hashed, lowercase (ISO 3166-1 alpha-2) */\n country?: string | string[];\n\n /** External IDs, unique per user. SHA-256 hash recommended */\n external_id?: string | string[];\n\n /** IPv4 or IPv6 address of client. Do NOT hash. */\n client_ip_address?: string;\n\n /** User agent string from browser. Do NOT hash. */\n client_user_agent?: string;\n\n /** fbclid parameter value from the URL. Do NOT hash. */\n fbclid?: string;\n\n /** Facebook click ID (_fbc cookie). Do NOT hash. */\n fbc?: string;\n\n /** Facebook browser ID (_fbp cookie). Do NOT hash. */\n fbp?: string;\n\n /** Subscription ID for the transaction. Do NOT hash. */\n subscription_id?: string;\n\n /** Facebook login ID (App-Scoped ID). Do NOT hash. */\n fb_login_id?: number;\n\n /** Meta Lead Ad lead ID. Do NOT hash. */\n lead_id?: number;\n\n /** Anonymous install ID. App events only. Do NOT hash. */\n anon_id?: string;\n\n /** Mobile advertiser ID (GAID/IDFA). Do NOT hash. */\n madid?: string;\n\n /** Facebook Page ID. Do NOT hash. */\n page_id?: string;\n\n /** Messenger Page-scoped user ID. Do NOT hash. */\n page_scoped_user_id?: string;\n\n /** Click to WhatsApp ad click ID. Do NOT hash. */\n ctwa_clid?: string;\n\n /** Instagram business account ID. Do NOT hash. */\n ig_account_id?: string;\n\n /** Instagram-scoped user ID. Do NOT hash. */\n ig_sid?: string;\n}\n\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/custom-data\nexport interface StandardParameters {\n // Web and Offline parameters\n availability?: string;\n body_style?: string;\n checkin_date?: string;\n city?: string;\n condition_of_vehicle?: string;\n content_ids?: string[];\n content_type?: 'product' | 'product_group' | string;\n contents?: Array<{\n id: string;\n quantity?: number;\n item_price?: number;\n delivery_category?: string;\n }>;\n country?: string;\n currency?: string;\n delivery_category?: 'in_store' | 'curbside' | 'home_delivery' | string;\n departing_arrival_date?: string;\n departing_departure_date?: string;\n destination_airport?: string;\n destination_ids?: string[];\n dma_code?: string;\n drivetrain?: string;\n exterior_color?: string;\n fuel_type?: string;\n hotel_score?: number;\n interior_color?: string;\n lead_event_source?: string;\n lease_end_date?: string;\n lease_start_date?: string;\n listing_type?: string;\n make?: string;\n // @TODO is mileage an object?\n 'mileage.unit'?: string;\n 'mileage.value'?: number;\n model?: string;\n neighborhood?: string;\n net_revenue?: number;\n num_adults?: number;\n num_children?: number;\n num_infants?: number;\n num_items?: number;\n order_id?: string;\n origin_airport?: string;\n postal_code?: string;\n predicted_ltv?: number;\n preferred_baths_range?: string;\n preferred_beds_range?: string;\n preferred_neighborhoods?: string[];\n preferred_num_stops?: number;\n preferred_price_range?: string;\n preferred_star_ratings?: [number, number];\n price?: string;\n product_catalog_id?: string;\n property_type?: string;\n region?: string;\n returning_arrival_date?: string;\n returning_departure_date?: string;\n search_string?: string;\n state_of_vehicle?: string;\n suggested_destinations?: string[];\n suggested_home_listings?: string[];\n suggested_hotels?: string[];\n suggested_jobs?: string[];\n suggested_local_service_businesses?: string[];\n suggested_location_based_items?: string[];\n suggested_vehicles?: string[];\n transmission?: string;\n travel_class?: string;\n travel_end?: string;\n travel_start?: string;\n trim?: string;\n\n // App-specific parameters (with fb_ prefix)\n fb_availability?: string;\n fb_body_style?: string;\n fb_checkin_date?: string;\n fb_city?: string;\n fb_condition_of_vehicle?: string;\n fb_content_ids?: string[];\n fb_content_type?: string;\n fb_contents?: Array<{ id: string; quantity?: number; item_price?: number }>;\n fb_country?: string;\n fb_currency?: string;\n fb_delivery_category?: string;\n fb_departing_arrival_date?: string;\n fb_departing_departure_date?: string;\n fb_destination_airport?: string;\n fb_destination_ids?: string[];\n fb_dma_code?: string;\n fb_drivetrain?: string;\n fb_exterior_color?: string;\n fb_fuel_type?: string;\n fb_hotel_score?: number;\n fb_interior_color?: string;\n fb_lease_end_date?: string;\n fb_lease_start_date?: string;\n fb_listing_type?: string;\n fb_make?: string;\n // @TODO is fb_mileage an object?\n 'fb_mileage.unit'?: string;\n 'fb_mileage.value'?: number;\n fb_model?: string;\n fb_neighborhood?: string;\n fb_num_adults?: number;\n fb_num_children?: number;\n fb_num_infants?: number;\n fb_num_items?: number;\n fb_order_id?: string;\n fb_origin_airport?: string;\n fb_postal_code?: string;\n fb_predicted_ltv?: number;\n fb_preferred_baths_range?: string;\n fb_preferred_beds_range?: string;\n fb_preferred_neighborhoods?: string[];\n fb_preferred_num_stops?: number;\n fb_preferred_price_range?: string;\n fb_preferred_star_ratings?: [number, number];\n fb_price?: string;\n fb_product_catalog_id?: string;\n fb_property_type?: string;\n fb_region?: string;\n fb_returning_arrival_date?: string;\n fb_returning_departure_date?: string;\n fb_search_string?: string;\n fb_state_of_vehicle?: string;\n fb_suggested_destinations?: string[];\n fb_suggested_home_listings?: string[];\n fb_suggested_hotels?: string[];\n fb_suggested_jobs?: string[];\n fb_suggested_local_service_businesses?: string[];\n fb_suggested_location_based_items?: string[];\n fb_suggested_vehicles?: string[];\n fb_transmission?: string;\n fb_travel_class?: string;\n fb_travel_end?: string;\n fb_travel_start?: string;\n\n // Offline-specific parameters\n user_bucket?: string;\n value?: number;\n vin?: string;\n year?: number;\n item_number?: string;\n}\n\nexport interface OriginalEventDataParameters {\n event_name?: EventName;\n event_time?: number;\n order_id?: number;\n event_id?: string;\n}\n"],"mappings":"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","names":["import_core","import_server_core"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getMappingValue,isObject as isObject2}from"@walkeros/core";import{sendServer}from"@walkeros/server-core";import{isArray,isObject,isString}from"@walkeros/core";import{getHashServer}from"@walkeros/server-core";var trimLower=value=>value.trim().toLowerCase(),lettersAndNumbers=value=>value.toLowerCase().replace(/[^\p{L}\p{N}]/gu,""),name=value=>value.toLowerCase().replace(/\p{P}/gu,"").trim(),normalizers={em:trimLower,ph:value=>value.replace(/\D/g,"").replace(/^0+/,""),fn:name,ln:name,db:value=>{const date=value.trim();return/^\d{4}\p{P}?\d{2}\p{P}?\d{2}$/u.test(date)?date.replace(/\D/g,""):date},ge:value=>trimLower(value).charAt(0),ct:lettersAndNumbers,st:lettersAndNumbers,zp:value=>{const zip=trimLower(value);return/^\d{5}[\s-]?\d{4}$/.test(zip)?zip.slice(0,5):zip.replace(/[\s-]/g,"")},country:trimLower,external_id:value=>value};function getNormalizer(key,doNotHash=[]){if(Object.hasOwn(normalizers,key)&&!doNotHash.includes(key))return normalizers[key]}function hashValue(key,value,normalize,logger){const normalized=normalize(String(value));return"db"!==key||/^\d{8}$/.test(normalized)||logger?.warn("Meta user_data db is not YYYYMMDD after normalization and cannot match"),getHashServer(normalized)}async function processValue(key,value,normalize,logger){return normalize?isArray(value)?Promise.all(value.map(item=>hashValue(key,item,normalize,logger))):hashValue(key,value,normalize,logger):value}var userDataKeys=["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"];var push=async function(event,{config:config,rule:rule,data:data,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="website",doNotHash:doNotHash,test_event_code:test_event_code,url:url="https://graph.facebook.com/v22.0/",user_data:user_data}=config.settings,eventData=isObject2(data)?data:{},configData=config.data?await getMappingValue(event,config.data,{collector:collector}):{},userDataCustom=user_data?await getMappingValue(event,{map:user_data},{collector:collector}):{},mappedUserData={...isObject2(configData)&&isObject2(configData.user_data)?configData.user_data:{},...isObject2(userDataCustom)?userDataCustom:{},...isObject2(eventData.user_data)?eventData.user_data:{}},unknownKeys=function(userData){const known=userDataKeys;return Object.keys(userData).filter(key=>!known.includes(key))}(mappedUserData);unknownKeys.length&&logger.warn("Unknown Meta user_data keys dropped, use parameter names such as em and ph",{keys:unknownKeys});const userData=Object.fromEntries(Object.entries(mappedUserData).filter(([key])=>!unknownKeys.includes(key)));userData.fbclid&&(userData.fbc=function(clickId,time){if(!clickId)return;const version="fb",subdomainIndex="1",creationTime=time||Date.now();return`${version}.${subdomainIndex}.${creationTime}.${clickId}`}(userData.fbclid,collector?.session?.start||event.timestamp),delete userData.fbclid);const serverEvent={event_name:event.name,event_id:event.id,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,...eventData,user_data:userData};"website"===action_source&&event.source?.url&&(serverEvent.event_source_url=event.source.url);const hashedServerEvent=await async function(value,doNotHash=[],logger){if(!isObject(value))return value;const isUserData="user_data"in value,target=isUserData?value.user_data:value,result=(await Promise.all(Object.entries(target).map(async([k,v])=>[k,await processValue(k,v,isUserData?getNormalizer(k,doNotHash):void 0,logger)]))).reduce((acc,[k,v])=>(isString(k)&&(acc[k]=v),acc),{});return isUserData?{...value,user_data:result}:result}(serverEvent,doNotHash,logger),body={data:[hashedServerEvent]};test_event_code&&(body.test_event_code=test_event_code);const endpoint=`${url.replace(/\/+$/,"")}/${pixelId}/events`;logger.debug("Calling Meta API",{endpoint:endpoint,method:"POST",eventName:serverEvent.event_name,eventId:serverEvent.event_id});const sendServerFn=env?.sendServer||sendServer,result=await sendServerFn(endpoint,JSON.stringify(body),{headers:{Authorization:`Bearer ${accessToken}`}});logger.debug("Meta API response",{ok:!isObject2(result)||result.ok}),isObject2(result)&&!1===result.ok&&logger.throw(`Meta API error: ${JSON.stringify(result)}`)};var types_exports={},destinationMeta={type:"meta",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={...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationMeta;export{types_exports as DestinationMeta,index_default as default,destinationMeta};//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import{createMappingRoot,getMappingValue,isObject as isObject2}from"@walkeros/core";import{sendServer}from"@walkeros/server-core";import{isArray,isObject,isString}from"@walkeros/core";import{getHashServer}from"@walkeros/server-core";var trimLower=value=>value.trim().toLowerCase(),lettersAndNumbers=value=>value.toLowerCase().replace(/[^\p{L}\p{N}]/gu,""),name=value=>value.toLowerCase().replace(/\p{P}/gu,"").trim(),normalizers={em:trimLower,ph:value=>value.replace(/\D/g,"").replace(/^0+/,""),fn:name,ln:name,db:value=>{const date=value.trim();return/^\d{4}\p{P}?\d{2}\p{P}?\d{2}$/u.test(date)?date.replace(/\D/g,""):date},ge:value=>trimLower(value).charAt(0),ct:lettersAndNumbers,st:lettersAndNumbers,zp:value=>{const zip=trimLower(value);return/^\d{5}[\s-]?\d{4}$/.test(zip)?zip.slice(0,5):zip.replace(/[\s-]/g,"")},country:trimLower,external_id:value=>value};function getNormalizer(key,doNotHash=[]){if(Object.hasOwn(normalizers,key)&&!doNotHash.includes(key))return normalizers[key]}function hashValue(key,value,normalize,logger){const normalized=normalize(String(value));return"db"!==key||/^\d{8}$/.test(normalized)||logger?.warn("Meta user_data db is not YYYYMMDD after normalization and cannot match"),getHashServer(normalized)}async function processValue(key,value,normalize,logger){return normalize?isArray(value)?Promise.all(value.map(item=>hashValue(key,item,normalize,logger))):hashValue(key,value,normalize,logger):value}var userDataKeys=["em","ph","fn","ln","db","ge","ct","st","zp","country","external_id","client_ip_address","client_user_agent","fbc","fbp","subscription_id","fb_login_id","lead_id","anon_id","madid","page_id","page_scoped_user_id","ctwa_clid","ig_account_id","ig_sid","fbclid"];var push=async function(event,{config:config,rule:rule,data:data,ingest:ingest,collector:collector,env:env,logger:logger}){const{accessToken:accessToken,pixelId:pixelId,action_source:action_source="website",doNotHash:doNotHash,test_event_code:test_event_code,url:url="https://graph.facebook.com/v22.0/",user_data:user_data,ip:ip,userAgent:userAgent}=config.settings,eventData=isObject2(data)?data:{},configData=config.data?await getMappingValue(event,config.data,{collector:collector}):{},userDataCustom=user_data?await getMappingValue(event,{map:user_data},{collector:collector}):{},root=createMappingRoot(ingest,event),clientIp=await resolveClient(ip,DEFAULT_IP,root,collector),clientUserAgent=await resolveClient(userAgent,DEFAULT_USER_AGENT,root,collector),mappedUserData={...void 0!==clientIp?{client_ip_address:clientIp}:{},...void 0!==clientUserAgent?{client_user_agent:clientUserAgent}:{},...isObject2(configData)&&isObject2(configData.user_data)?configData.user_data:{},...isObject2(userDataCustom)?userDataCustom:{},...isObject2(eventData.user_data)?eventData.user_data:{}},unknownKeys=function(userData){const known=userDataKeys;return Object.keys(userData).filter(key=>!known.includes(key))}(mappedUserData);unknownKeys.length&&logger.warn("Unknown Meta user_data keys dropped, use parameter names such as em and ph",{keys:unknownKeys});const userData=Object.fromEntries(Object.entries(mappedUserData).filter(([key])=>!unknownKeys.includes(key)));userData.fbclid&&(userData.fbc=function(clickId,time){if(!clickId)return;const version="fb",subdomainIndex="1",creationTime=time||Date.now();return`${version}.${subdomainIndex}.${creationTime}.${clickId}`}(userData.fbclid,collector?.session?.start||event.timestamp),delete userData.fbclid);const serverEvent={event_name:event.name,event_id:event.id,event_time:Math.round((event.timestamp||Date.now())/1e3),action_source:action_source,...eventData,user_data:userData};"website"===action_source&&event.source?.url&&(serverEvent.event_source_url=event.source.url);const hashedServerEvent=await async function(value,doNotHash=[],logger){if(!isObject(value))return value;const isUserData="user_data"in value,target=isUserData?value.user_data:value,result=(await Promise.all(Object.entries(target).map(async([k,v])=>[k,await processValue(k,v,isUserData?getNormalizer(k,doNotHash):void 0,logger)]))).reduce((acc,[k,v])=>(isString(k)&&(acc[k]=v),acc),{});return isUserData?{...value,user_data:result}:result}(serverEvent,doNotHash,logger),body={data:[hashedServerEvent]};test_event_code&&(body.test_event_code=test_event_code);const endpoint=`${url.replace(/\/+$/,"")}/${pixelId}/events`;logger.debug("Calling Meta API",{endpoint:endpoint,method:"POST",eventName:serverEvent.event_name,eventId:serverEvent.event_id});const sendServerFn=env?.sendServer||sendServer,result=await sendServerFn(endpoint,JSON.stringify(body),{headers:{Authorization:`Bearer ${accessToken}`}});logger.debug("Meta API response",{ok:!isObject2(result)||result.ok}),isObject2(result)&&!1===result.ok&&logger.throw(`Meta API error: ${JSON.stringify(result)}`)},DEFAULT_IP=["ingest.ip","event.user.ip"],DEFAULT_USER_AGENT=["ingest.userAgent","event.user.userAgent"];async function resolveClient(setting,fallback,root,collector){if(!1===setting)return;const value=await getMappingValue(root,setting??fallback,{collector:collector});return"string"==typeof value&&""!==value?value:void 0}var types_exports={},destinationMeta={type:"meta",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={...settings,accessToken:accessToken,pixelId:pixelId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationMeta;export{types_exports as DestinationMeta,index_default as default,destinationMeta};//# 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/userData.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 ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n BodyParameters,\n CustomerInformationParameters,\n PushFn,\n ServerEventParameters,\n Env,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashEvent } from './hash';\nimport { getUnknownUserDataKeys } from './userData';\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 = 'website',\n doNotHash,\n test_event_code,\n url = 'https://graph.facebook.com/v22.0/',\n user_data,\n } = config.settings!;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data, { collector })\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n\n const mappedUserData = {\n // Destination config\n ...(isObject(configData) && isObject(configData.user_data)\n ? configData.user_data\n : {}),\n // Custom user_data\n ...(isObject(userDataCustom) ? userDataCustom : {}),\n // Event mapping\n ...(isObject(eventData.user_data) ? eventData.user_data : {}),\n };\n\n // Unknown keys are never hashed, so drop them instead of sending cleartext\n const unknownKeys = getUnknownUserDataKeys(mappedUserData);\n if (unknownKeys.length)\n logger.warn(\n 'Unknown Meta user_data keys dropped, use parameter names such as em and ph',\n { keys: unknownKeys },\n );\n\n const userData: CustomerInformationParameters = Object.fromEntries(\n Object.entries(mappedUserData).filter(\n ([key]) => !unknownKeys.includes(key),\n ),\n );\n\n if (userData.fbclid) {\n userData.fbc = formatClickId(\n userData.fbclid,\n collector?.session?.start || event.timestamp,\n );\n delete userData.fbclid;\n }\n const serverEvent: ServerEventParameters = {\n event_name: event.name,\n event_id: event.id,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n ...eventData,\n user_data: userData,\n };\n\n if (action_source === 'website' && event.source?.url)\n serverEvent.event_source_url = event.source.url;\n\n const hashedServerEvent = await hashEvent(serverEvent, doNotHash, logger);\n\n const body: BodyParameters = { data: [hashedServerEvent] };\n\n // Test event code\n if (test_event_code) body.test_event_code = test_event_code;\n\n const endpoint = `${url.replace(/\\/+$/, '')}/${pixelId}/events`;\n logger.debug('Calling Meta API', {\n endpoint,\n method: 'POST',\n eventName: serverEvent.event_name,\n eventId: serverEvent.event_id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n logger.debug('Meta API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Meta API error: ${JSON.stringify(result)}`);\n }\n};\n\nfunction formatClickId(clickId: unknown, time?: number): string | undefined {\n // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#2--format-clickid\n\n if (!clickId) return;\n\n // Version is always \"fb\"\n const version = 'fb';\n\n // Subdomain ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)\n const subdomainIndex = '1';\n\n // Get the current timestamp in milliseconds (or when the fbclid was observed)\n const creationTime = time || Date.now();\n\n return `${version}.${subdomainIndex}.${creationTime}.${clickId}`;\n}\n","import type { Logger, WalkerOS } from '@walkeros/core';\nimport { isArray, isObject, isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\ntype Normalizer = (value: string) => string;\n\nconst trimLower: Normalizer = (value) => value.trim().toLowerCase();\n\nconst lettersAndNumbers: Normalizer = (value) =>\n value.toLowerCase().replace(/[^\\p{L}\\p{N}]/gu, '');\n\nconst name: Normalizer = (value) =>\n value.toLowerCase().replace(/\\p{P}/gu, '').trim();\n\n// Formatting rules per key, applied before hashing:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nconst normalizers: Record<string, Normalizer> = {\n em: trimLower,\n ph: (value) => value.replace(/\\D/g, '').replace(/^0+/, ''),\n fn: name,\n ln: name,\n db: (value) => {\n const date = value.trim();\n return /^\\d{4}\\p{P}?\\d{2}\\p{P}?\\d{2}$/u.test(date)\n ? date.replace(/\\D/g, '')\n : date;\n },\n ge: (value) => trimLower(value).charAt(0),\n ct: lettersAndNumbers,\n st: lettersAndNumbers,\n zp: (value) => {\n const zip = trimLower(value);\n if (/^\\d{5}[\\s-]?\\d{4}$/.test(zip)) return zip.slice(0, 5);\n return zip.replace(/[\\s-]/g, '');\n },\n country: trimLower,\n external_id: (value) => value,\n};\n\n// Keys listed in doNotHash are sent exactly as mapped, without normalization\nfunction getNormalizer(\n key: string,\n doNotHash: string[] = [],\n): Normalizer | undefined {\n if (!Object.hasOwn(normalizers, key) || doNotHash.includes(key)) return;\n return normalizers[key];\n}\n\nfunction hashValue(\n key: string,\n value: unknown,\n normalize: Normalizer,\n logger?: Logger.Instance,\n): Promise<string> {\n const normalized = normalize(String(value));\n if (key === 'db' && !/^\\d{8}$/.test(normalized))\n logger?.warn(\n 'Meta user_data db is not YYYYMMDD after normalization and cannot match',\n );\n return getHashServer(normalized);\n}\n\ntype HashableValue = WalkerOS.AnyObject | unknown | unknown[];\n\nasync function processValue(\n key: string,\n value: unknown,\n normalize?: Normalizer,\n logger?: Logger.Instance,\n): Promise<unknown> {\n if (!normalize) return value;\n if (isArray(value)) {\n return Promise.all(\n value.map((item) => hashValue(key, item, normalize, logger)),\n );\n }\n return hashValue(key, value, normalize, logger);\n}\n\nexport async function hashEvent<T extends HashableValue>(\n value: T,\n doNotHash: string[] = [],\n logger?: Logger.Instance,\n): Promise<T> {\n if (!isObject(value)) return value;\n\n const isUserData = 'user_data' in value;\n const target = (isUserData ? value.user_data : value) as WalkerOS.AnyObject;\n\n const entries = await Promise.all(\n Object.entries(target).map(async ([k, v]) => [\n k,\n await processValue(\n k,\n v,\n isUserData ? getNormalizer(k, doNotHash) : undefined,\n logger,\n ),\n ]),\n );\n\n const result = entries.reduce((acc, [k, v]) => {\n if (isString(k)) acc[k] = v;\n return acc;\n }, {} as WalkerOS.AnyObject);\n\n return isUserData ? { ...value, user_data: result } : (result as T);\n}\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\nimport type { userDataKeys } from '../userData';\n\nexport interface Settings {\n accessToken: string;\n pixelId: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n test_event_code?: string;\n url?: string;\n user_data?: UserDataMap;\n}\n\nexport type UserDataKey = (typeof userDataKeys)[number];\n\n/** Mapping of Meta customer information parameters to event values */\nexport type UserDataMap = Partial<Record<UserDataKey, WalkerOSMapping.Value>>;\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// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/main-body\nexport interface BodyParameters {\n data: Array<ServerEventParameters>;\n test_event_code?: string;\n}\n\n/**\n * Represents the top‑level parameters for a server event sent via Meta's Conversions API.\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport interface ServerEventParameters extends StandardParameters {\n /** The event name or custom event identifier. Required for deduplication. */\n event_name: EventName;\n\n /** Unix timestamp (in seconds) when the event actually occurred. GMT timezone. */\n event_time: number;\n\n /** Map of customer information for matching (emails, phone, etc.). */\n user_data: CustomerInformationParameters;\n\n /** Additional business data about the event. */\n custom_data?: Record<string, unknown>;\n\n /** URL of the page where the event occurred. */\n event_source_url?: string;\n\n /** If true, exclude this event from ads optimization (only attribution). */\n opt_out?: boolean;\n\n /** Unique ID for deduplication across Pixel and CAPI. */\n event_id?: string;\n\n /** Source of the event (e.g., website, app). */\n action_source: ActionSource;\n\n /** Processing options (e.g., ['LDU'] for CCPA limited data use). */\n data_processing_options?: DataProcessingOption[];\n\n /** Country code for data processing option (1 = USA, 0 = auto‑geolocate). */\n data_processing_options_country?: number;\n\n /** State code for data processing option (1000 = California, 0 = auto). */\n data_processing_options_state?: number;\n\n /** App‑specific data (required if action_source is 'app'). */\n app_data?: AppData;\n\n /** HTTP referrer header of the event. */\n referrer_url?: string;\n\n /** Metadata to link delayed events to past acquisition events. */\n original_event_data?: OriginalEventDataParameters;\n\n /** User segment for more context about the customer's relationship. */\n customer_segmentation?: CustomerSegmentation;\n}\n\nexport type EventName =\n | 'AddPaymentInfo'\n | 'AddToCart'\n | 'AddToWishlist'\n | 'CompleteRegistration'\n | 'Contact'\n | 'CustomizeProduct'\n | 'Donate'\n | 'FindLocation'\n | 'InitiateCheckout'\n | 'Lead'\n | 'Purchase'\n | 'Schedule'\n | 'Search'\n | 'StartTrial'\n | 'SubmitApplication'\n | 'Subscribe'\n | 'ViewContent'\n | string;\n\nexport type ActionSource =\n | 'email'\n | 'website'\n | 'app'\n | 'phone_call'\n | 'chat'\n | 'physical_store'\n | 'system_generated'\n | 'business_messaging'\n | 'other';\n\nexport type DataProcessingOption = 'LDU';\n\nexport type CustomerSegmentation =\n | 'new_customer_to_business'\n | 'new_customer_to_business_line'\n | 'new_customer_to_product_area'\n | 'new_customer_to_medium'\n | 'existing_customer_to_business'\n | 'existing_customer_to_business_line'\n | 'existing_customer_to_product_area'\n | 'existing_customer_to_medium'\n | 'customer_in_loyalty_program';\n\n/** Extended device info for app events (Android version 'a2', iOS 'i2') */\nexport interface AppData {\n /**\n * Comma-separated array of strings with fixed order:\n * [sdk_version, os_version, device_model, device_brand,\n * screen_width, screen_height, ...]\n */\n extinfo: string[];\n}\n\n// Customer Information Parameters\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nexport interface CustomerInformationParameters {\n /** Email(s), SHA-256 hashed, lowercase and trimmed */\n em?: string | string[];\n\n /** Phone number(s), SHA-256 hashed, E.164 format (no leading 0s or symbols) */\n ph?: string | string[];\n\n /** First name(s), SHA-256 hashed, lowercase */\n fn?: string | string[];\n\n /** Last name(s), SHA-256 hashed, lowercase */\n ln?: string | string[];\n\n /** Date(s) of birth in YYYYMMDD, SHA-256 hashed */\n db?: string | string[];\n\n /** Gender(s) in lowercase single letter (\"m\", \"f\", etc.), SHA-256 hashed */\n ge?: string | string[];\n\n /** City name(s), SHA-256 hashed, lowercase */\n ct?: string | string[];\n\n /** State abbreviation(s), SHA-256 hashed, lowercase (e.g., \"ca\", \"ny\") */\n st?: string | string[];\n\n /** ZIP or postal code(s), SHA-256 hashed, lowercase */\n zp?: string | string[];\n\n /** Country code(s), SHA-256 hashed, lowercase (ISO 3166-1 alpha-2) */\n country?: string | string[];\n\n /** External IDs, unique per user. SHA-256 hash recommended */\n external_id?: string | string[];\n\n /** IPv4 or IPv6 address of client. Do NOT hash. */\n client_ip_address?: string;\n\n /** User agent string from browser. Do NOT hash. */\n client_user_agent?: string;\n\n /** fbclid parameter value from the URL. Do NOT hash. */\n fbclid?: string;\n\n /** Facebook click ID (_fbc cookie). Do NOT hash. */\n fbc?: string;\n\n /** Facebook browser ID (_fbp cookie). Do NOT hash. */\n fbp?: string;\n\n /** Subscription ID for the transaction. Do NOT hash. */\n subscription_id?: string;\n\n /** Facebook login ID (App-Scoped ID). Do NOT hash. */\n fb_login_id?: number;\n\n /** Meta Lead Ad lead ID. Do NOT hash. */\n lead_id?: number;\n\n /** Anonymous install ID. App events only. Do NOT hash. */\n anon_id?: string;\n\n /** Mobile advertiser ID (GAID/IDFA). Do NOT hash. */\n madid?: string;\n\n /** Facebook Page ID. Do NOT hash. */\n page_id?: string;\n\n /** Messenger Page-scoped user ID. Do NOT hash. */\n page_scoped_user_id?: string;\n\n /** Click to WhatsApp ad click ID. Do NOT hash. */\n ctwa_clid?: string;\n\n /** Instagram business account ID. Do NOT hash. */\n ig_account_id?: string;\n\n /** Instagram-scoped user ID. Do NOT hash. */\n ig_sid?: string;\n}\n\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/custom-data\nexport interface StandardParameters {\n // Web and Offline parameters\n availability?: string;\n body_style?: string;\n checkin_date?: string;\n city?: string;\n condition_of_vehicle?: string;\n content_ids?: string[];\n content_type?: 'product' | 'product_group' | string;\n contents?: Array<{\n id: string;\n quantity?: number;\n item_price?: number;\n delivery_category?: string;\n }>;\n country?: string;\n currency?: string;\n delivery_category?: 'in_store' | 'curbside' | 'home_delivery' | string;\n departing_arrival_date?: string;\n departing_departure_date?: string;\n destination_airport?: string;\n destination_ids?: string[];\n dma_code?: string;\n drivetrain?: string;\n exterior_color?: string;\n fuel_type?: string;\n hotel_score?: number;\n interior_color?: string;\n lead_event_source?: string;\n lease_end_date?: string;\n lease_start_date?: string;\n listing_type?: string;\n make?: string;\n // @TODO is mileage an object?\n 'mileage.unit'?: string;\n 'mileage.value'?: number;\n model?: string;\n neighborhood?: string;\n net_revenue?: number;\n num_adults?: number;\n num_children?: number;\n num_infants?: number;\n num_items?: number;\n order_id?: string;\n origin_airport?: string;\n postal_code?: string;\n predicted_ltv?: number;\n preferred_baths_range?: string;\n preferred_beds_range?: string;\n preferred_neighborhoods?: string[];\n preferred_num_stops?: number;\n preferred_price_range?: string;\n preferred_star_ratings?: [number, number];\n price?: string;\n product_catalog_id?: string;\n property_type?: string;\n region?: string;\n returning_arrival_date?: string;\n returning_departure_date?: string;\n search_string?: string;\n state_of_vehicle?: string;\n suggested_destinations?: string[];\n suggested_home_listings?: string[];\n suggested_hotels?: string[];\n suggested_jobs?: string[];\n suggested_local_service_businesses?: string[];\n suggested_location_based_items?: string[];\n suggested_vehicles?: string[];\n transmission?: string;\n travel_class?: string;\n travel_end?: string;\n travel_start?: string;\n trim?: string;\n\n // App-specific parameters (with fb_ prefix)\n fb_availability?: string;\n fb_body_style?: string;\n fb_checkin_date?: string;\n fb_city?: string;\n fb_condition_of_vehicle?: string;\n fb_content_ids?: string[];\n fb_content_type?: string;\n fb_contents?: Array<{ id: string; quantity?: number; item_price?: number }>;\n fb_country?: string;\n fb_currency?: string;\n fb_delivery_category?: string;\n fb_departing_arrival_date?: string;\n fb_departing_departure_date?: string;\n fb_destination_airport?: string;\n fb_destination_ids?: string[];\n fb_dma_code?: string;\n fb_drivetrain?: string;\n fb_exterior_color?: string;\n fb_fuel_type?: string;\n fb_hotel_score?: number;\n fb_interior_color?: string;\n fb_lease_end_date?: string;\n fb_lease_start_date?: string;\n fb_listing_type?: string;\n fb_make?: string;\n // @TODO is fb_mileage an object?\n 'fb_mileage.unit'?: string;\n 'fb_mileage.value'?: number;\n fb_model?: string;\n fb_neighborhood?: string;\n fb_num_adults?: number;\n fb_num_children?: number;\n fb_num_infants?: number;\n fb_num_items?: number;\n fb_order_id?: string;\n fb_origin_airport?: string;\n fb_postal_code?: string;\n fb_predicted_ltv?: number;\n fb_preferred_baths_range?: string;\n fb_preferred_beds_range?: string;\n fb_preferred_neighborhoods?: string[];\n fb_preferred_num_stops?: number;\n fb_preferred_price_range?: string;\n fb_preferred_star_ratings?: [number, number];\n fb_price?: string;\n fb_product_catalog_id?: string;\n fb_property_type?: string;\n fb_region?: string;\n fb_returning_arrival_date?: string;\n fb_returning_departure_date?: string;\n fb_search_string?: string;\n fb_state_of_vehicle?: string;\n fb_suggested_destinations?: string[];\n fb_suggested_home_listings?: string[];\n fb_suggested_hotels?: string[];\n fb_suggested_jobs?: string[];\n fb_suggested_local_service_businesses?: string[];\n fb_suggested_location_based_items?: string[];\n fb_suggested_vehicles?: string[];\n fb_transmission?: string;\n fb_travel_class?: string;\n fb_travel_end?: string;\n fb_travel_start?: string;\n\n // Offline-specific parameters\n user_bucket?: string;\n value?: number;\n vin?: string;\n year?: number;\n item_number?: string;\n}\n\nexport interface OriginalEventDataParameters {\n event_name?: EventName;\n event_time?: number;\n order_id?: number;\n event_id?: string;\n}\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMeta from './types';\n\nexport const destinationMeta: Destination = {\n type: 'meta',\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 destinationMeta;\n"],"mappings":"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","names":["isObject","isObject"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/hash.ts","../src/userData.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 ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n BodyParameters,\n CustomerInformationParameters,\n PushFn,\n ServerEventParameters,\n Env,\n} from './types';\nimport type { Collector, Mapping as WalkerOSMapping } from '@walkeros/core';\nimport { createMappingRoot, getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashEvent } from './hash';\nimport { getUnknownUserDataKeys } from './userData';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, ingest, collector, env, logger },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'website',\n doNotHash,\n test_event_code,\n url = 'https://graph.facebook.com/v22.0/',\n user_data,\n ip,\n userAgent,\n } = config.settings!;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data, { collector })\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n\n // Client IP and user agent auto-fill, overridden by any mapped value\n const root = createMappingRoot(ingest, event);\n const clientIp = await resolveClient(ip, DEFAULT_IP, root, collector);\n const clientUserAgent = await resolveClient(\n userAgent,\n DEFAULT_USER_AGENT,\n root,\n collector,\n );\n\n const mappedUserData = {\n ...(clientIp !== undefined ? { client_ip_address: clientIp } : {}),\n ...(clientUserAgent !== undefined\n ? { client_user_agent: clientUserAgent }\n : {}),\n // Destination config\n ...(isObject(configData) && isObject(configData.user_data)\n ? configData.user_data\n : {}),\n // Custom user_data\n ...(isObject(userDataCustom) ? userDataCustom : {}),\n // Event mapping\n ...(isObject(eventData.user_data) ? eventData.user_data : {}),\n };\n\n // Unknown keys are never hashed, so drop them instead of sending cleartext\n const unknownKeys = getUnknownUserDataKeys(mappedUserData);\n if (unknownKeys.length)\n logger.warn(\n 'Unknown Meta user_data keys dropped, use parameter names such as em and ph',\n { keys: unknownKeys },\n );\n\n const userData: CustomerInformationParameters = Object.fromEntries(\n Object.entries(mappedUserData).filter(\n ([key]) => !unknownKeys.includes(key),\n ),\n );\n\n if (userData.fbclid) {\n userData.fbc = formatClickId(\n userData.fbclid,\n collector?.session?.start || event.timestamp,\n );\n delete userData.fbclid;\n }\n const serverEvent: ServerEventParameters = {\n event_name: event.name,\n event_id: event.id,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n ...eventData,\n user_data: userData,\n };\n\n if (action_source === 'website' && event.source?.url)\n serverEvent.event_source_url = event.source.url;\n\n const hashedServerEvent = await hashEvent(serverEvent, doNotHash, logger);\n\n const body: BodyParameters = { data: [hashedServerEvent] };\n\n // Test event code\n if (test_event_code) body.test_event_code = test_event_code;\n\n const endpoint = `${url.replace(/\\/+$/, '')}/${pixelId}/events`;\n logger.debug('Calling Meta API', {\n endpoint,\n method: 'POST',\n eventName: serverEvent.event_name,\n eventId: serverEvent.event_id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(body), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n logger.debug('Meta API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Meta API error: ${JSON.stringify(result)}`);\n }\n};\n\nconst DEFAULT_IP: WalkerOSMapping.Value = ['ingest.ip', 'event.user.ip'];\nconst DEFAULT_USER_AGENT: WalkerOSMapping.Value = [\n 'ingest.userAgent',\n 'event.user.userAgent',\n];\n\n/** A client IP or user agent setting resolved to a non-empty string. */\nasync function resolveClient(\n setting: WalkerOSMapping.Value | false | undefined,\n fallback: WalkerOSMapping.Value,\n root: WalkerOSMapping.Root,\n collector: Collector.Instance,\n): Promise<string | undefined> {\n if (setting === false) return undefined;\n const value = await getMappingValue(root, setting ?? fallback, { collector });\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction formatClickId(clickId: unknown, time?: number): string | undefined {\n // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#2--format-clickid\n\n if (!clickId) return;\n\n // Version is always \"fb\"\n const version = 'fb';\n\n // Subdomain ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)\n const subdomainIndex = '1';\n\n // Get the current timestamp in milliseconds (or when the fbclid was observed)\n const creationTime = time || Date.now();\n\n return `${version}.${subdomainIndex}.${creationTime}.${clickId}`;\n}\n","import type { Logger, WalkerOS } from '@walkeros/core';\nimport { isArray, isObject, isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\ntype Normalizer = (value: string) => string;\n\nconst trimLower: Normalizer = (value) => value.trim().toLowerCase();\n\nconst lettersAndNumbers: Normalizer = (value) =>\n value.toLowerCase().replace(/[^\\p{L}\\p{N}]/gu, '');\n\nconst name: Normalizer = (value) =>\n value.toLowerCase().replace(/\\p{P}/gu, '').trim();\n\n// Formatting rules per key, applied before hashing:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nconst normalizers: Record<string, Normalizer> = {\n em: trimLower,\n ph: (value) => value.replace(/\\D/g, '').replace(/^0+/, ''),\n fn: name,\n ln: name,\n db: (value) => {\n const date = value.trim();\n return /^\\d{4}\\p{P}?\\d{2}\\p{P}?\\d{2}$/u.test(date)\n ? date.replace(/\\D/g, '')\n : date;\n },\n ge: (value) => trimLower(value).charAt(0),\n ct: lettersAndNumbers,\n st: lettersAndNumbers,\n zp: (value) => {\n const zip = trimLower(value);\n if (/^\\d{5}[\\s-]?\\d{4}$/.test(zip)) return zip.slice(0, 5);\n return zip.replace(/[\\s-]/g, '');\n },\n country: trimLower,\n external_id: (value) => value,\n};\n\n// Keys listed in doNotHash are sent exactly as mapped, without normalization\nfunction getNormalizer(\n key: string,\n doNotHash: string[] = [],\n): Normalizer | undefined {\n if (!Object.hasOwn(normalizers, key) || doNotHash.includes(key)) return;\n return normalizers[key];\n}\n\nfunction hashValue(\n key: string,\n value: unknown,\n normalize: Normalizer,\n logger?: Logger.Instance,\n): Promise<string> {\n const normalized = normalize(String(value));\n if (key === 'db' && !/^\\d{8}$/.test(normalized))\n logger?.warn(\n 'Meta user_data db is not YYYYMMDD after normalization and cannot match',\n );\n return getHashServer(normalized);\n}\n\ntype HashableValue = WalkerOS.AnyObject | unknown | unknown[];\n\nasync function processValue(\n key: string,\n value: unknown,\n normalize?: Normalizer,\n logger?: Logger.Instance,\n): Promise<unknown> {\n if (!normalize) return value;\n if (isArray(value)) {\n return Promise.all(\n value.map((item) => hashValue(key, item, normalize, logger)),\n );\n }\n return hashValue(key, value, normalize, logger);\n}\n\nexport async function hashEvent<T extends HashableValue>(\n value: T,\n doNotHash: string[] = [],\n logger?: Logger.Instance,\n): Promise<T> {\n if (!isObject(value)) return value;\n\n const isUserData = 'user_data' in value;\n const target = (isUserData ? value.user_data : value) as WalkerOS.AnyObject;\n\n const entries = await Promise.all(\n Object.entries(target).map(async ([k, v]) => [\n k,\n await processValue(\n k,\n v,\n isUserData ? getNormalizer(k, doNotHash) : undefined,\n logger,\n ),\n ]),\n );\n\n const result = entries.reduce((acc, [k, v]) => {\n if (isString(k)) acc[k] = v;\n return acc;\n }, {} as WalkerOS.AnyObject);\n\n return isUserData ? { ...value, user_data: result } : (result as T);\n}\n","// Customer information parameters accepted in user_data:\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n// fbclid is not sent; the destination turns it into fbc.\nexport const userDataKeys = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n 'client_ip_address',\n 'client_user_agent',\n 'fbc',\n 'fbp',\n 'subscription_id',\n 'fb_login_id',\n 'lead_id',\n 'anon_id',\n 'madid',\n 'page_id',\n 'page_scoped_user_id',\n 'ctwa_clid',\n 'ig_account_id',\n 'ig_sid',\n 'fbclid',\n] as const;\n\nexport function getUnknownUserDataKeys(userData: object): string[] {\n const known: readonly string[] = userDataKeys;\n return Object.keys(userData).filter((key) => !known.includes(key));\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\nimport type { userDataKeys } from '../userData';\n\nexport interface Settings {\n accessToken: string;\n pixelId: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n test_event_code?: string;\n url?: string;\n user_data?: UserDataMap;\n /**\n * Client IP, sent as user_data.client_ip_address. Resolves against\n * { ingest, event }. `false` switches it off.\n * @default ['ingest.ip', 'event.user.ip']\n */\n ip?: WalkerOSMapping.Value | false;\n /**\n * Client user agent, sent as user_data.client_user_agent. Resolves against\n * { ingest, event }. `false` switches it off.\n * @default ['ingest.userAgent', 'event.user.userAgent']\n */\n userAgent?: WalkerOSMapping.Value | false;\n}\n\nexport type UserDataKey = (typeof userDataKeys)[number];\n\n/** Mapping of Meta customer information parameters to event values */\nexport type UserDataMap = Partial<Record<UserDataKey, WalkerOSMapping.Value>>;\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// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/main-body\nexport interface BodyParameters {\n data: Array<ServerEventParameters>;\n test_event_code?: string;\n}\n\n/**\n * Represents the top‑level parameters for a server event sent via Meta's Conversions API.\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport interface ServerEventParameters extends StandardParameters {\n /** The event name or custom event identifier. Required for deduplication. */\n event_name: EventName;\n\n /** Unix timestamp (in seconds) when the event actually occurred. GMT timezone. */\n event_time: number;\n\n /** Map of customer information for matching (emails, phone, etc.). */\n user_data: CustomerInformationParameters;\n\n /** Additional business data about the event. */\n custom_data?: Record<string, unknown>;\n\n /** URL of the page where the event occurred. */\n event_source_url?: string;\n\n /** If true, exclude this event from ads optimization (only attribution). */\n opt_out?: boolean;\n\n /** Unique ID for deduplication across Pixel and CAPI. */\n event_id?: string;\n\n /** Source of the event (e.g., website, app). */\n action_source: ActionSource;\n\n /** Processing options (e.g., ['LDU'] for CCPA limited data use). */\n data_processing_options?: DataProcessingOption[];\n\n /** Country code for data processing option (1 = USA, 0 = auto‑geolocate). */\n data_processing_options_country?: number;\n\n /** State code for data processing option (1000 = California, 0 = auto). */\n data_processing_options_state?: number;\n\n /** App‑specific data (required if action_source is 'app'). */\n app_data?: AppData;\n\n /** HTTP referrer header of the event. */\n referrer_url?: string;\n\n /** Metadata to link delayed events to past acquisition events. */\n original_event_data?: OriginalEventDataParameters;\n\n /** User segment for more context about the customer's relationship. */\n customer_segmentation?: CustomerSegmentation;\n}\n\nexport type EventName =\n | 'AddPaymentInfo'\n | 'AddToCart'\n | 'AddToWishlist'\n | 'CompleteRegistration'\n | 'Contact'\n | 'CustomizeProduct'\n | 'Donate'\n | 'FindLocation'\n | 'InitiateCheckout'\n | 'Lead'\n | 'Purchase'\n | 'Schedule'\n | 'Search'\n | 'StartTrial'\n | 'SubmitApplication'\n | 'Subscribe'\n | 'ViewContent'\n | string;\n\nexport type ActionSource =\n | 'email'\n | 'website'\n | 'app'\n | 'phone_call'\n | 'chat'\n | 'physical_store'\n | 'system_generated'\n | 'business_messaging'\n | 'other';\n\nexport type DataProcessingOption = 'LDU';\n\nexport type CustomerSegmentation =\n | 'new_customer_to_business'\n | 'new_customer_to_business_line'\n | 'new_customer_to_product_area'\n | 'new_customer_to_medium'\n | 'existing_customer_to_business'\n | 'existing_customer_to_business_line'\n | 'existing_customer_to_product_area'\n | 'existing_customer_to_medium'\n | 'customer_in_loyalty_program';\n\n/** Extended device info for app events (Android version 'a2', iOS 'i2') */\nexport interface AppData {\n /**\n * Comma-separated array of strings with fixed order:\n * [sdk_version, os_version, device_model, device_brand,\n * screen_width, screen_height, ...]\n */\n extinfo: string[];\n}\n\n// Customer Information Parameters\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nexport interface CustomerInformationParameters {\n /** Email(s), SHA-256 hashed, lowercase and trimmed */\n em?: string | string[];\n\n /** Phone number(s), SHA-256 hashed, E.164 format (no leading 0s or symbols) */\n ph?: string | string[];\n\n /** First name(s), SHA-256 hashed, lowercase */\n fn?: string | string[];\n\n /** Last name(s), SHA-256 hashed, lowercase */\n ln?: string | string[];\n\n /** Date(s) of birth in YYYYMMDD, SHA-256 hashed */\n db?: string | string[];\n\n /** Gender(s) in lowercase single letter (\"m\", \"f\", etc.), SHA-256 hashed */\n ge?: string | string[];\n\n /** City name(s), SHA-256 hashed, lowercase */\n ct?: string | string[];\n\n /** State abbreviation(s), SHA-256 hashed, lowercase (e.g., \"ca\", \"ny\") */\n st?: string | string[];\n\n /** ZIP or postal code(s), SHA-256 hashed, lowercase */\n zp?: string | string[];\n\n /** Country code(s), SHA-256 hashed, lowercase (ISO 3166-1 alpha-2) */\n country?: string | string[];\n\n /** External IDs, unique per user. SHA-256 hash recommended */\n external_id?: string | string[];\n\n /** IPv4 or IPv6 address of client. Do NOT hash. */\n client_ip_address?: string;\n\n /** User agent string from browser. Do NOT hash. */\n client_user_agent?: string;\n\n /** fbclid parameter value from the URL. Do NOT hash. */\n fbclid?: string;\n\n /** Facebook click ID (_fbc cookie). Do NOT hash. */\n fbc?: string;\n\n /** Facebook browser ID (_fbp cookie). Do NOT hash. */\n fbp?: string;\n\n /** Subscription ID for the transaction. Do NOT hash. */\n subscription_id?: string;\n\n /** Facebook login ID (App-Scoped ID). Do NOT hash. */\n fb_login_id?: number;\n\n /** Meta Lead Ad lead ID. Do NOT hash. */\n lead_id?: number;\n\n /** Anonymous install ID. App events only. Do NOT hash. */\n anon_id?: string;\n\n /** Mobile advertiser ID (GAID/IDFA). Do NOT hash. */\n madid?: string;\n\n /** Facebook Page ID. Do NOT hash. */\n page_id?: string;\n\n /** Messenger Page-scoped user ID. Do NOT hash. */\n page_scoped_user_id?: string;\n\n /** Click to WhatsApp ad click ID. Do NOT hash. */\n ctwa_clid?: string;\n\n /** Instagram business account ID. Do NOT hash. */\n ig_account_id?: string;\n\n /** Instagram-scoped user ID. Do NOT hash. */\n ig_sid?: string;\n}\n\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/custom-data\nexport interface StandardParameters {\n // Web and Offline parameters\n availability?: string;\n body_style?: string;\n checkin_date?: string;\n city?: string;\n condition_of_vehicle?: string;\n content_ids?: string[];\n content_type?: 'product' | 'product_group' | string;\n contents?: Array<{\n id: string;\n quantity?: number;\n item_price?: number;\n delivery_category?: string;\n }>;\n country?: string;\n currency?: string;\n delivery_category?: 'in_store' | 'curbside' | 'home_delivery' | string;\n departing_arrival_date?: string;\n departing_departure_date?: string;\n destination_airport?: string;\n destination_ids?: string[];\n dma_code?: string;\n drivetrain?: string;\n exterior_color?: string;\n fuel_type?: string;\n hotel_score?: number;\n interior_color?: string;\n lead_event_source?: string;\n lease_end_date?: string;\n lease_start_date?: string;\n listing_type?: string;\n make?: string;\n // @TODO is mileage an object?\n 'mileage.unit'?: string;\n 'mileage.value'?: number;\n model?: string;\n neighborhood?: string;\n net_revenue?: number;\n num_adults?: number;\n num_children?: number;\n num_infants?: number;\n num_items?: number;\n order_id?: string;\n origin_airport?: string;\n postal_code?: string;\n predicted_ltv?: number;\n preferred_baths_range?: string;\n preferred_beds_range?: string;\n preferred_neighborhoods?: string[];\n preferred_num_stops?: number;\n preferred_price_range?: string;\n preferred_star_ratings?: [number, number];\n price?: string;\n product_catalog_id?: string;\n property_type?: string;\n region?: string;\n returning_arrival_date?: string;\n returning_departure_date?: string;\n search_string?: string;\n state_of_vehicle?: string;\n suggested_destinations?: string[];\n suggested_home_listings?: string[];\n suggested_hotels?: string[];\n suggested_jobs?: string[];\n suggested_local_service_businesses?: string[];\n suggested_location_based_items?: string[];\n suggested_vehicles?: string[];\n transmission?: string;\n travel_class?: string;\n travel_end?: string;\n travel_start?: string;\n trim?: string;\n\n // App-specific parameters (with fb_ prefix)\n fb_availability?: string;\n fb_body_style?: string;\n fb_checkin_date?: string;\n fb_city?: string;\n fb_condition_of_vehicle?: string;\n fb_content_ids?: string[];\n fb_content_type?: string;\n fb_contents?: Array<{ id: string; quantity?: number; item_price?: number }>;\n fb_country?: string;\n fb_currency?: string;\n fb_delivery_category?: string;\n fb_departing_arrival_date?: string;\n fb_departing_departure_date?: string;\n fb_destination_airport?: string;\n fb_destination_ids?: string[];\n fb_dma_code?: string;\n fb_drivetrain?: string;\n fb_exterior_color?: string;\n fb_fuel_type?: string;\n fb_hotel_score?: number;\n fb_interior_color?: string;\n fb_lease_end_date?: string;\n fb_lease_start_date?: string;\n fb_listing_type?: string;\n fb_make?: string;\n // @TODO is fb_mileage an object?\n 'fb_mileage.unit'?: string;\n 'fb_mileage.value'?: number;\n fb_model?: string;\n fb_neighborhood?: string;\n fb_num_adults?: number;\n fb_num_children?: number;\n fb_num_infants?: number;\n fb_num_items?: number;\n fb_order_id?: string;\n fb_origin_airport?: string;\n fb_postal_code?: string;\n fb_predicted_ltv?: number;\n fb_preferred_baths_range?: string;\n fb_preferred_beds_range?: string;\n fb_preferred_neighborhoods?: string[];\n fb_preferred_num_stops?: number;\n fb_preferred_price_range?: string;\n fb_preferred_star_ratings?: [number, number];\n fb_price?: string;\n fb_product_catalog_id?: string;\n fb_property_type?: string;\n fb_region?: string;\n fb_returning_arrival_date?: string;\n fb_returning_departure_date?: string;\n fb_search_string?: string;\n fb_state_of_vehicle?: string;\n fb_suggested_destinations?: string[];\n fb_suggested_home_listings?: string[];\n fb_suggested_hotels?: string[];\n fb_suggested_jobs?: string[];\n fb_suggested_local_service_businesses?: string[];\n fb_suggested_location_based_items?: string[];\n fb_suggested_vehicles?: string[];\n fb_transmission?: string;\n fb_travel_class?: string;\n fb_travel_end?: string;\n fb_travel_start?: string;\n\n // Offline-specific parameters\n user_bucket?: string;\n value?: number;\n vin?: string;\n year?: number;\n item_number?: string;\n}\n\nexport interface OriginalEventDataParameters {\n event_name?: EventName;\n event_time?: number;\n order_id?: number;\n event_id?: string;\n}\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMeta from './types';\n\nexport const destinationMeta: Destination = {\n type: 'meta',\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 destinationMeta;\n"],"mappings":"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","names":["isObject","isObject"]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/server-destination-meta",
|
|
4
|
-
"version": "4.7.0
|
|
4
|
+
"version": "4.7.0",
|
|
5
5
|
"type": "destination",
|
|
6
6
|
"platform": [
|
|
7
7
|
"server"
|
|
8
8
|
],
|
|
9
|
+
"exports": {},
|
|
9
10
|
"docs": "https://www.walkeros.io/docs/destinations/server/meta-capi",
|
|
10
11
|
"source": "https://github.com/elbwalker/walkerOS/tree/main/packages/server/destinations/meta/src"
|
|
11
12
|
},
|
|
@@ -98,6 +99,30 @@
|
|
|
98
99
|
"$ref": "#/definitions/MappingValue"
|
|
99
100
|
},
|
|
100
101
|
"description": "Mapping of Meta customer information parameters to event values, applied to every event. Keys must be Meta's short names such as em and ph (like { em: 'user.email', ph: 'user.phone' })"
|
|
102
|
+
},
|
|
103
|
+
"ip": {
|
|
104
|
+
"anyOf": [
|
|
105
|
+
{
|
|
106
|
+
"$ref": "#/definitions/MappingValue"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"type": "boolean",
|
|
110
|
+
"const": false
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"description": "Client IP, sent as user_data.client_ip_address. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.client_ip_address wins."
|
|
114
|
+
},
|
|
115
|
+
"userAgent": {
|
|
116
|
+
"anyOf": [
|
|
117
|
+
{
|
|
118
|
+
"$ref": "#/definitions/MappingValue"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"type": "boolean",
|
|
122
|
+
"const": false
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"description": "Client user agent, sent as user_data.client_user_agent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.client_user_agent wins."
|
|
101
126
|
}
|
|
102
127
|
},
|
|
103
128
|
"required": [
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/server-destination-meta",
|
|
3
3
|
"description": "Meta server destination for walkerOS",
|
|
4
|
-
"version": "4.7.0
|
|
4
|
+
"version": "4.7.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"update": "npx npm-check-updates -u && npm update"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@walkeros/core": "4.7.0
|
|
39
|
-
"@walkeros/server-core": "4.7.0
|
|
38
|
+
"@walkeros/core": "4.7.0",
|
|
39
|
+
"@walkeros/server-core": "4.7.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@walkeros/collector": "4.7.0
|
|
42
|
+
"@walkeros/collector": "4.7.0"
|
|
43
43
|
},
|
|
44
44
|
"repository": {
|
|
45
45
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|