Developer Docs
Node.js SDK

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-node

Or with Yarn:

yarn add @convultra/sdk-node

Quick 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)
})
OptionTypeDefaultDescription
timeoutnumber5000Request timeout in milliseconds
retriesnumber2Number of automatic retries on network failure
debugbooleanfalseLog 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 typeDescription
purchaseCompleted purchase or transaction
leadLead form submission
signupUser registration
subscriptionSubscription start or renewal
downloadFile download
contactContact form submission
scheduleAppointment booking
Any custom stringCustom 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.