{"_id":"@actovision/facebook-conversion-api-nodejs","_rev":"2-cf33a555c704b427a7bdb6e49d1d3966","name":"@actovision/facebook-conversion-api-nodejs","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@actovision/facebook-conversion-api-nodejs","version":"0.1.0","keywords":["facebook","meta","conversion","conversions","capi","pixel","tracking","analytics"],"author":{"name":"Actovision"},"license":"MIT","_id":"@actovision/facebook-conversion-api-nodejs@0.1.0","maintainers":[{"name":"suryak_actovision","email":"surya.k@actovision.in"}],"homepage":"https://github.com/actovision/actovision-facebook-conversion-api-nodejs#readme","bugs":{"url":"https://github.com/actovision/actovision-facebook-conversion-api-nodejs/issues"},"dist":{"shasum":"2c4bde4898293b53bff12cc46da0855b17db2151","tarball":"https://registry.npmjs.org/@actovision/facebook-conversion-api-nodejs/-/facebook-conversion-api-nodejs-0.1.0.tgz","fileCount":9,"integrity":"sha512-okk/XkVOGLv/Z2bAipsnTaVmtNDOKE0NAet3NTt++yAY44LhARNtq6CXdgpdkx3Lc3172huQ2hQy82Y40LTiuQ==","signatures":[{"sig":"MEYCIQDh6iGVv6k52UnqNJXNU6qWyj+y0gCTUXX07DfJGL53kwIhAOFYnEkOnK8WJLKhsnHD8Kz3SB1rgqWx6iDIyuU6yUKY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97938},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"fa5cd92553e1e7030830c7c1eb2e1d843968bde1","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","clean":"rm -rf dist coverage","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"suryak_actovision","email":"surya.k@actovision.in"},"repository":{"url":"git+https://github.com/actovision/actovision-facebook-conversion-api-nodejs.git","type":"git"},"_npmVersion":"11.6.0","description":"Node.js / TypeScript client for Meta's Conversions API (CAPI). FacebookCapiClient with full parameter coverage (user_data, app_data, referrer_url, LDU/CCPA, offline events), automatic SHA-256 hashing + normalization, batching up to 1000 events per request","directories":{},"sideEffects":false,"_nodeVersion":"24.10.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.0","typescript":"^5.6.0","@types/node":"^22.9.0"},"_npmOperationalInternal":{"tmp":"tmp/facebook-conversion-api-nodejs_0.1.0_1777032051131_0.6373506613283333","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@actovision/facebook-conversion-api-nodejs","version":"0.2.0","description":"Node.js / TypeScript client for Meta's Conversions API (CAPI). FacebookCapiClient with full parameter coverage (user_data, app_data, referrer_url, LDU/CCPA, offline events), automatic SHA-256 hashing + normalization, batching up to 1000 events per request","keywords":["facebook","meta","conversion","conversions","capi","pixel","tracking","analytics"],"author":{"name":"Actovision"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/actovision/actovision-facebook-conversion-api-nodejs.git"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","clean":"rm -rf dist coverage","prepublishOnly":"pnpm run test -- --run && pnpm run build"},"devDependencies":{"@types/node":"^22.9.0","tsup":"^8.3.0","typescript":"^5.6.0","vitest":"^2.1.0"},"engines":{"node":">=22.0.0"},"publishConfig":{"access":"public"},"gitHead":"179eb44751c4bc99ec447419cc8a9d917e8105c7","_id":"@actovision/facebook-conversion-api-nodejs@0.2.0","bugs":{"url":"https://github.com/actovision/actovision-facebook-conversion-api-nodejs/issues"},"homepage":"https://github.com/actovision/actovision-facebook-conversion-api-nodejs#readme","_nodeVersion":"26.5.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-MoG+wT8pmKcplidv0kQOh2zigN4vU9b1wEjs5HMZbGzRE/L96RlnZM+M2o70vigMYseL991NJVEQNuZVMIPt0Q==","shasum":"f899a525580ec28a49452557490fb95ac87898e3","tarball":"https://registry.npmjs.org/@actovision/facebook-conversion-api-nodejs/-/facebook-conversion-api-nodejs-0.2.0.tgz","fileCount":9,"unpackedSize":99246,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC17FK22dlVVVA08fL2hheWTQxvag7DGxWe0Ye3RBaCKwIhAOnM365uPRpRPXK5YxTMIlV+Hzc3H3vbd6mYDLU5f1jh"}]},"_npmUser":{"name":"suryak_actovision","email":"surya.k@actovision.in"},"directories":{},"maintainers":[{"name":"suryak_actovision","email":"surya.k@actovision.in"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/facebook-conversion-api-nodejs_0.2.0_1786021551146_0.23885596010083598"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-24T12:00:51.004Z","modified":"2026-08-06T13:05:51.491Z","0.1.0":"2026-04-24T12:00:51.261Z","0.2.0":"2026-08-06T13:05:51.288Z"},"bugs":{"url":"https://github.com/actovision/actovision-facebook-conversion-api-nodejs/issues"},"author":{"name":"Actovision"},"license":"MIT","homepage":"https://github.com/actovision/actovision-facebook-conversion-api-nodejs#readme","keywords":["facebook","meta","conversion","conversions","capi","pixel","tracking","analytics"],"repository":{"type":"git","url":"git+https://github.com/actovision/actovision-facebook-conversion-api-nodejs.git"},"description":"Node.js / TypeScript client for Meta's Conversions API (CAPI). FacebookCapiClient with full parameter coverage (user_data, app_data, referrer_url, LDU/CCPA, offline events), automatic SHA-256 hashing + normalization, batching up to 1000 events per request","maintainers":[{"name":"suryak_actovision","email":"surya.k@actovision.in"}],"readme":"# @actovision/facebook-conversion-api-nodejs\n\nNode.js / TypeScript client for [Meta's Conversions API](https://developers.facebook.com/docs/marketing-api/conversions-api/). Direct Graph API calls — **zero runtime dependencies**.\n\n- Full CAPI parameter coverage: every standard event, every `user_data` signal (`em`, `ph`, `fn`, `ln`, `ge`, `db`, `ct`, `st`, `zp`, `country`, `external_id`, `client_ip_address`, `client_user_agent`, `fbp`, `fbc`, `fb_login_id`, `subscription_id`, `lead_id`, `madid`, `anon_id`, `page_id`, `page_scoped_user_id`, `ctwa_clid`, `ig_account_id`, `ig_sid`), `app_data` for app-source events, `referrer_url`, LDU/CCPA, test events, deduplication via `event_id`\n- Automatic SHA-256 hashing + Meta's normalization rules (idempotent)\n- Batching up to 1,000 events per request, retry on 5xx with exponential backoff\n- Defaults to Graph API **v22.0** — configurable via `apiVersion`\n\n## Install\n\n```bash\nnpm install @actovision/facebook-conversion-api-nodejs\n# or\npnpm add @actovision/facebook-conversion-api-nodejs\n```\n\nRequires Node.js ≥ 22 (uses global `fetch` and `node:crypto`).\n\n## Quick start\n\n```ts\nimport { FacebookCapiClient } from '@actovision/facebook-conversion-api-nodejs'\n\nconst capi = new FacebookCapiClient({\n  accessToken: process.env.FB_ACCESS_TOKEN!,\n  pixelId: process.env.FB_PIXEL_ID!,\n  actionSource: 'website',\n})\n\nawait capi.trackEvent({\n  eventName: 'Purchase',\n  eventId: 'order-12345', // use for browser-pixel deduplication\n  eventSourceUrl: 'https://shop.example.com/thankyou',\n  userData: {\n    emails: ['customer@example.com'],\n    phones: ['+1 555 123 4567'],\n    clientIpAddress: '203.0.113.42',\n    clientUserAgent: 'Mozilla/5.0 ...',\n    fbp: 'fb.1.1554763741205.12345',\n    fbc: 'fb.1.1554763741205.AbCdEf',\n  },\n  customData: {\n    currency: 'USD',\n    value: 99.99,\n    contents: [{ id: 'sku-1', quantity: 1, item_price: 99.99 }],\n  },\n})\n```\n\n## API\n\n### `new FacebookCapiClient(options)`\n\n| Option | Type | Default |\n| --- | --- | --- |\n| `accessToken` | `string` | **required** |\n| `pixelId` | `string` | **required** |\n| `actionSource` | `ActionSource` | `'website'` |\n| `apiVersion` | `string` | `'v22.0'` |\n| `testEventCode` | `string` | — |\n| `timeoutMs` | `number` | `10_000` |\n| `retries` | `number` | `2` (retries only on 5xx / network errors) |\n| `fetch` | `typeof fetch` | global `fetch` — override for tests |\n\n### Methods\n\n- `setUserData(userData)` — merge persistent user data used on every subsequent event.\n- `resetUserData(userData?)` — replace persistent user data.\n- `trackEvent(event)` — send one event. Returns `Promise<FacebookCapiResponse>`.\n- `trackEvents(events)` — send up to 1000 events in one request.\n\n### Automatic hashing & normalization\n\nThe following fields are normalized (per [Meta's rules](https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters)) and SHA-256 hashed before transmission:\n\n`emails`, `phones`, `firstName`, `lastName`, `gender`, `dateOfBirth`, `city`, `state`, `zip`, `country`, `externalId`\n\nNetwork signals that must **not** be hashed are passed through unchanged: `clientIpAddress`, `clientUserAgent`, `fbp`, `fbc`, `facebookLoginId`, `subscriptionId`, `leadId`, `madid`, `anonId`, `pageId`, `pageScopedUserId`, `ctwaClid`, `igAccountId`, `igSid`.\n\nHashing is idempotent — if you pass a value that already looks like a SHA-256 hex digest, it is forwarded as-is.\n\n## Standard events\n\nEvery Meta standard event is supported. Attach persistent customer data once via `setUserData()`, then call `trackEvent()` per-action. Event names are case-sensitive — use the names exactly as shown.\n\n```ts\nimport { FacebookCapiClient } from '@actovision/facebook-conversion-api-nodejs'\n\nconst capi = new FacebookCapiClient({\n  accessToken: process.env.FB_ACCESS_TOKEN!,\n  pixelId: process.env.FB_PIXEL_ID!,\n  actionSource: 'website',\n})\n\n// Attach network signals and identity that are stable per-session.\ncapi.setUserData({\n  emails: ['customer@example.com'],\n  phones: ['+1 555 123 4567'],\n  clientIpAddress: '203.0.113.42',\n  clientUserAgent: 'Mozilla/5.0 ...',\n  fbp: 'fb.1.1554763741205.12345',\n  fbc: 'fb.1.1554763741205.AbCdEf',\n})\n\n// Purchase — completed transaction\nawait capi.trackEvent({\n  eventName: 'Purchase',\n  eventId: 'ORDER-12345',\n  eventSourceUrl: 'https://shop.example.com/thankyou',\n  customData: {\n    value: 99.99,\n    currency: 'USD',\n    order_id: 'ORDER-12345',\n    contents: [{ id: 'sku-1', quantity: 1, item_price: 99.99 }],\n    content_ids: ['sku-1'],\n    content_type: 'product',\n  },\n})\n\n// AddToCart\nawait capi.trackEvent({\n  eventName: 'AddToCart',\n  eventId: 'evt-addtocart-1',\n  customData: {\n    content_ids: ['sku-1'],\n    contents: [{ id: 'sku-1', quantity: 1, item_price: 49.99 }],\n    content_type: 'product',\n    value: 49.99,\n    currency: 'USD',\n  },\n})\n\n// InitiateCheckout\nawait capi.trackEvent({\n  eventName: 'InitiateCheckout',\n  eventId: 'evt-checkout-1',\n  customData: {\n    content_ids: ['sku-1', 'sku-2'],\n    num_items: 2,\n    value: 79.98,\n    currency: 'USD',\n  },\n})\n\n// AddPaymentInfo\nawait capi.trackEvent({\n  eventName: 'AddPaymentInfo',\n  eventId: 'evt-payinfo-1',\n  customData: { value: 79.98, currency: 'USD' },\n})\n\n// ViewContent\nawait capi.trackEvent({\n  eventName: 'ViewContent',\n  eventId: 'evt-view-1',\n  customData: {\n    content_ids: ['sku-1'],\n    content_name: 'Running Shoes',\n    content_category: 'Footwear',\n    content_type: 'product',\n    value: 49.99,\n    currency: 'USD',\n  },\n})\n\n// Search\nawait capi.trackEvent({\n  eventName: 'Search',\n  eventId: 'evt-search-1',\n  customData: {\n    search_string: 'running shoes',\n    content_ids: ['sku-1', 'sku-2'],\n    content_category: 'Footwear',\n  },\n})\n\n// Lead\nawait capi.trackEvent({\n  eventName: 'Lead',\n  eventId: 'evt-lead-1',\n  customData: { content_name: 'Newsletter Signup', value: 0, currency: 'USD' },\n})\n\n// CompleteRegistration\nawait capi.trackEvent({\n  eventName: 'CompleteRegistration',\n  eventId: 'evt-signup-1',\n  customData: {\n    content_name: 'Free Plan',\n    status: 'completed',\n    value: 0,\n    currency: 'USD',\n  },\n})\n\n// Subscribe\nawait capi.trackEvent({\n  eventName: 'Subscribe',\n  eventId: 'evt-sub-1',\n  customData: { value: 9.99, currency: 'USD', predicted_ltv: 120 },\n})\n\n// StartTrial\nawait capi.trackEvent({\n  eventName: 'StartTrial',\n  eventId: 'evt-trial-1',\n  customData: { value: 0, currency: 'USD', predicted_ltv: 120 },\n})\n\n// AddToWishlist\nawait capi.trackEvent({\n  eventName: 'AddToWishlist',\n  eventId: 'evt-wish-1',\n  customData: { content_ids: ['sku-1'], value: 49.99, currency: 'USD' },\n})\n\n// FindLocation\nawait capi.trackEvent({\n  eventName: 'FindLocation',\n  eventId: 'evt-find-1',\n  customData: { content_name: 'Downtown Store' },\n})\n\n// Schedule\nawait capi.trackEvent({\n  eventName: 'Schedule',\n  eventId: 'evt-sched-1',\n  customData: { content_name: 'Consultation' },\n})\n\n// SubmitApplication\nawait capi.trackEvent({\n  eventName: 'SubmitApplication',\n  eventId: 'evt-app-1',\n  customData: { value: 0, currency: 'USD' },\n})\n\n// Donate\nawait capi.trackEvent({\n  eventName: 'Donate',\n  eventId: 'evt-donate-1',\n  customData: { value: 25, currency: 'USD' },\n})\n\n// Contact\nawait capi.trackEvent({\n  eventName: 'Contact',\n  eventId: 'evt-contact-1',\n})\n\n// PageView\nawait capi.trackEvent({\n  eventName: 'PageView',\n  eventId: 'evt-pv-1',\n  eventSourceUrl: 'https://shop.example.com/',\n})\n```\n\nNeed a custom event? Pass any string for `eventName` — typed as `EventName = StandardEventName | (string & {})`.\n\n## App events\n\nFor app-source events, set `actionSource: 'app'` and pass `appData`:\n\n```ts\nawait capi.trackEvent({\n  eventName: 'Purchase',\n  eventId: 'order-1',\n  actionSource: 'app',\n  userData: { madid: '<IDFA or GAID>', emails: ['buyer@example.com'] },\n  customData: { currency: 'USD', value: 9.99 },\n  appData: {\n    advertiserTrackingEnabled: 1,           // iOS ATT consent (boolean coerced to 0/1)\n    applicationTrackingEnabled: 1,\n    extinfo: ['i2', 'com.example.app', '1.0', '1', '17.0', 'iPhone15,2', 'en_US', 'PST', 'Verizon', 390, 844, 3, 6, 8, 128],\n    vendorId: 'IDFV-...',\n  },\n})\n```\n\n## Offline conversions\n\nFor offline events (in-store purchases, phone sales, chat closures), set `actionSource` accordingly (`physical_store`, `phone_call`, `email`, `chat`, `other`). Meta accepts offline events up to **62 days** after the conversion.\n\n## Deduplication with the browser pixel\n\nPass the same `eventId` that your browser pixel uses as the third `fbq('track', ..., { eventID })` argument. Meta will collapse the two deliveries into one event. See [`@actovision/facebook-conversion-api-nextjs`](https://github.com/actovision/actovision-facebook-conversion-api-nextjs) for a turnkey Next.js setup.\n\n## Errors\n\n- `FacebookCapiError` — thrown on 4xx / non-retryable 5xx. Exposes `.status`, `.body`, `.fbtraceId`.\n- `FacebookCapiNetworkError` — thrown when fetch itself fails (timeout, DNS, connection reset) after the retry budget.\n\n## Singleton usage\n\nFor simple apps with a single pixel, a process-wide singleton is exported:\n\n```ts\nimport { facebookConversionAPI } from '@actovision/facebook-conversion-api-nodejs'\n\nfacebookConversionAPI.init({ accessToken, pixelId, actionSource: 'website' })\nfacebookConversionAPI.setUserData({ emails: ['a@b.com'] })\nawait facebookConversionAPI.trackEvent({ eventName: 'PageView' })\n```\n\nPrefer `new FacebookCapiClient(...)` if you need multiple pixels, want dependency injection, or care about test isolation.\n\n## License\n\n[MIT](./LICENSE) © 2026 [Actovision](https://github.com/actovision).\n\nFree to use in commercial and open-source projects. The license text must be included in copies or substantial portions of the software.\n","readmeFilename":"README.md"}