@plainrouter/sdk package from server-side Node.js code. Plainrouter validates the event, normalizes and hashes supported identity fields, and sends eligible events to the Meta dataset connected to your workspace.
Before you begin
You need:- Node.js
22.22.2or later in the Node 22 release line. - A Signals workspace secret stored only on your server.
- An active Meta destination.
- A consent decision that permits downstream advertising use. See Server-side tracking consent.
Install the Node.js SDK
Install@plainrouter/sdk:
import from a .mjs file or from a project whose package.json contains "type": "module".
Send a purchase
StorePLAINROUTER_SIGNAL_SECRET in your server environment. The SDK option signalTrackerSecret is its compatibility name; it expects a Signals workspace secret. Keep the configured client out of browser bundles.
Pass the recorded three-field consent object from your order or CMP records. The function refuses partial or denied advertising consent; it does not obtain consent. Supply the actual purchase time and consent-capture time from your order records. Reuse a stable, non-personal order ID for retries, and send money as a decimal string such as "49.90".
- JavaScript
- TypeScript
fbp or fbc when unavailable; see browser identifier formats.
Validate a TypeScript payload
The SDK exports a runtime schema when data crosses an untrusted boundary:Retry without creating another event
Keep the sameevent_id when a timeout or queue retry repeats the same logical purchase:
- A new event returns HTTP
202withduplicate: false. - A previously accepted
event_idreturns HTTP200withduplicate: true. - Changing the ID on each retry defeats idempotency and can create duplicate conversions.
signalq("track", ...) call generates its own ID and cannot accept the purchase:${order.id} ID used here. Choose the backend or the managed browser purchase recipe as the purchase owner. Do not also send a purchase from Stripe verified revenue for the same checkout.
For a durable backend integration:
- Confirm settlement on your server and read the recorded consent decision. A browser success-page visit is insufficient.
- Persist one event payload per paid order, including
event_id, the original purchase time, decimal amount, and the applicable consent snapshot. Use a unique record in your database to prevent concurrent jobs creating separate purchases. - Send that stored payload from your job. On an uncertain timeout, retry the same ID and payload; do not rebuild it with the current time or fresh identity data. Check that advertising use is still permitted before a later retry.
- Mark ingestion complete after
202or a duplicate200; inspect destination delivery separately. A duplicate receipt does not update or enrich the first accepted event.
Confirm delivery
The202 response means Plainrouter accepted the event for processing. It does not mean Meta has accepted the destination delivery yet.
Use Signal health and performance or retrieve the event with getEvent to inspect its delivery state. During setup, you can also use Meta Test Events mode through the destination operations in the Conversion API reference.
event_id returned by sendPurchase. An accepted delivery confirms Meta acceptance; queued, sent, or retrying remains pending. An empty list is not acceptance. For failed:* or skipped:*, inspect the delivery explanation before replaying anything. Handle 401 by checking credentials, 404 by checking ID, scope, and retention, and 422 by correcting the request fields.