Node.js SDK
The Convultra Node.js SDK enables server-side conversion tracking from your backend. Use it when conversions happen outside the browser — order processing, webhook handlers, CRM integrations, or anywhere you need to track events from your server.
Requirements
- Node.js 14 or higher
- A valid Convultra API key (from Dashboard → Projects → API Keys)
Installation
npm install @convultra/sdk-nodeOr with Yarn:
yarn add @convultra/sdk-nodeQuick start
const { ConvultraClient } = require('@convultra/sdk-node')
const convultra = new ConvultraClient('proj_your_api_key')
await convultra.track('purchase', {
value: 99.99,
currency: 'USD',
orderId: 'order_123',
userEmail: '[email protected]',
})The Node.js SDK sends events directly to the Convultra API over HTTPS. Events are forwarded to connected ad platforms the same way as browser SDK events.
Initialization
const { ConvultraClient } = require('@convultra/sdk-node')
const convultra = new ConvultraClient('proj_your_api_key', {
// Optional configuration
timeout: 5000, // Request timeout in ms (default: 5000)
retries: 2, // Number of retries on failure (default: 2)
debug: false, // Enable debug logging (default: false)
})| Option | Type | Default | Description |
|---|---|---|---|
timeout | number | 5000 | Request timeout in milliseconds |
retries | number | 2 | Number of automatic retries on network failure |
debug | boolean | false | Log requests and responses to console |
Tracking events
track(eventType, data)
The primary method for sending any conversion event.
await convultra.track('purchase', {
orderId: 'order_8842',
value: 149.99,
currency: 'USD',
userEmail: '[email protected]',
items: [
{ id: 'prod_001', name: 'Running Shoes', price: 89.99, quantity: 1 },
{ id: 'prod_044', name: 'Sport Socks 3-Pack', price: 19.99, quantity: 3 }
]
})Supported event types:
| Event type | Description |
|---|---|
purchase | Completed purchase or transaction |
lead | Lead form submission |
signup | User registration |
subscription | Subscription start or renewal |
download | File download |
contact | Contact form submission |
schedule | Appointment booking |
| Any custom string | Custom event type (e.g., trial_start, webinar_registration) |
Enhanced conversions
Include user data for enhanced conversion matching. The SDK hashes all PII fields (email, phone, name, address) with SHA-256 before sending.
await convultra.track('purchase', {
orderId: 'order_8842',
value: 149.99,
currency: 'USD',
// User data for enhanced matching
userEmail: '[email protected]',
userPhone: '+14155551234',
userFirstName: 'Sarah',
userLastName: 'Chen',
userAddress: {
street: '123 Market St',
city: 'San Francisco',
region: 'CA',
postalCode: '94105',
country: 'US'
}
})User data fields prefixed with user (userEmail, userPhone, userFirstName, userLastName, userAddress) are automatically detected, hashed, and sent as enhanced conversion data.
Batch events
Send multiple events in a single API call for better performance when processing large volumes.
await convultra.trackBatch([
{
eventType: 'purchase',
data: {
orderId: 'order_001',
value: 49.99,
currency: 'USD',
userEmail: '[email protected]'
}
},
{
eventType: 'purchase',
data: {
orderId: 'order_002',
value: 129.99,
currency: 'USD',
userEmail: '[email protected]'
}
},
{
eventType: 'lead',
data: {
leadId: 'lead_003',
value: 25.00,
userEmail: '[email protected]'
}
}
])Batch requests accept up to 100 events per call. For larger volumes, split into multiple batch calls.
Error handling
All SDK methods return promises. Handle errors with try/catch or .catch():
try {
await convultra.track('purchase', {
orderId: 'order_123',
value: 99.99,
currency: 'USD',
userEmail: '[email protected]'
})
console.log('Conversion tracked successfully')
} catch (error) {
console.error('Failed to track conversion:', error.message)
// error.code contains the error type
// 'INVALID_API_KEY' — API key is invalid or revoked
// 'RATE_LIMITED' — Too many requests, retry after delay
// 'NETWORK_ERROR' — Network failure after all retries
// 'VALIDATION_ERROR' — Invalid event data
}The SDK automatically retries on transient network errors (configurable via the retries option). Non-retryable errors (invalid API key, validation errors) fail immediately.
Use cases
Express.js order webhook
const express = require('express')
const { ConvultraClient } = require('@convultra/sdk-node')
const app = express()
const convultra = new ConvultraClient('proj_your_api_key')
app.post('/webhooks/order-completed', express.json(), async (req, res) => {
const { orderId, total, currency, customer } = req.body
try {
await convultra.track('purchase', {
orderId,
value: total,
currency,
userEmail: customer.email,
userFirstName: customer.firstName,
userLastName: customer.lastName
})
res.json({ status: 'tracked' })
} catch (error) {
console.error('Tracking failed:', error.message)
// Still return 200 — do not block the order flow
res.json({ status: 'tracking_failed', error: error.message })
}
})
app.listen(3000)Stripe webhook handler
const { ConvultraClient } = require('@convultra/sdk-node')
const convultra = new ConvultraClient('proj_your_api_key')
// Inside your Stripe webhook handler
async function handleCheckoutCompleted(session) {
await convultra.track('purchase', {
orderId: session.id,
value: session.amount_total / 100, // Stripe uses cents
currency: session.currency.toUpperCase(),
userEmail: session.customer_details.email,
userFirstName: session.customer_details.name?.split(' ')[0],
userLastName: session.customer_details.name?.split(' ').slice(1).join(' ')
})
}CRM lead sync
const { ConvultraClient } = require('@convultra/sdk-node')
const convultra = new ConvultraClient('proj_your_api_key')
async function syncLeadToConvultra(lead) {
await convultra.track('lead', {
leadId: lead.id,
value: lead.estimatedValue,
source: lead.source,
userEmail: lead.email,
userPhone: lead.phone,
userFirstName: lead.firstName,
userLastName: lead.lastName
})
}Batch processing from a database
const { ConvultraClient } = require('@convultra/sdk-node')
const convultra = new ConvultraClient('proj_your_api_key')
async function backfillOrders(orders) {
// Process in batches of 100
for (let i = 0; i < orders.length; i += 100) {
const batch = orders.slice(i, i + 100).map(order => ({
eventType: 'purchase',
data: {
orderId: order.id,
value: order.total,
currency: order.currency,
userEmail: order.customerEmail
}
}))
await convultra.trackBatch(batch)
console.log(`Tracked batch ${i / 100 + 1} (${batch.length} events)`)
}
}ESM / TypeScript
The SDK supports both CommonJS and ES modules:
const { ConvultraClient } = require('@convultra/sdk-node')
const convultra = new ConvultraClient('proj_your_api_key')Browser vs. Node.js: The browser SDK (@convultra/sdk-js) and Node.js SDK (@convultra/sdk-node) are separate packages. The browser SDK auto-captures click IDs, sessions, and device data. The Node.js SDK is for server-side events only and does not track browser context.