Skip to main content

track()

Tracks a custom event for a user.

Signature​

async track(
identifier: string,
eventName: string,
properties?: Record<string, any>
): Promise<void>

Parameters​

identifier​

  • Type: string
  • Required: Yes
  • Description: Unique identifier for the user

Must match the identifier used in identify() calls.

eventName​

  • Type: string
  • Required: Yes
  • Description: Name of the event to track

Use descriptive, consistent naming (e.g., purchase_completed, page_viewed, button_clicked).

properties​

  • Type: Record<string, any>
  • Required: No
  • Default: {}
  • Description: Additional data about the event

Returns​

Promise<void> - Resolves when the event is tracked successfully.

Throws​

  • Error: If identifier or event name is empty
  • Network errors: If the request fails

Identifier Consistency​

Use Consistent Identifiers

The identifier parameter must match the identifier used in identify(). See Consistent Identifiers for best practices.

Usage Examples​

Basic Event Tracking​

await client.track('user123', 'page_viewed', {
page: '/pricing',
referrer: '/home'
});

Purchase Event​

await client.track('user123', 'purchase_completed', {
order_id: 'order_789',
amount: 99.99,
currency: 'USD',
items: [
{
product_id: 'prod_123',
name: 'Premium Plan',
price: 99.99,
quantity: 1
}
],
payment_method: 'credit_card'
});

Feature Usage​

await client.track('user123', 'feature_used', {
feature_name: 'export_data',
export_format: 'csv',
file_size_bytes: 1024000,
timestamp: new Date().toISOString()
});

Button Click​

await client.track('user123', 'button_clicked', {
button_id: 'cta_signup',
page: '/home',
campaign: 'summer_2025'
});

Event Naming Best Practices​

Be Specific and Descriptive​

// ✅ Good
await client.track('user123', 'checkout_payment_failed', {
error_code: 'insufficient_funds',
payment_method: 'credit_card'
});

// ❌ Bad - Too vague
await client.track('user123', 'error', {
type: 'payment'
});

Validation​

// ❌ Throws: Identifier cannot be empty
await client.track('', 'purchase_completed', { amount: 99.99 });

// ❌ Throws: Event name cannot be empty
await client.track('user123', '', { amount: 99.99 });

// ✅ Valid
await client.track('user123', 'purchase_completed', { amount: 99.99 });

// ✅ Valid - Properties are optional
await client.track('user123', 'page_viewed');

Error Handling​

try {
await client.track('user123', 'purchase_completed', {
amount: 99.99,
currency: 'USD'
});
console.log('Event tracked successfully');
} catch (error) {
if (error.message.includes('Identifier cannot be empty')) {
console.error('Invalid user identifier');
} else if (error.message.includes('Event name cannot be empty')) {
console.error('Invalid event name');
} else if (error.response?.status === 429) {
console.error('Rate limit exceeded');
} else {
console.error('Failed to track event:', error.message);
}
}

Real-World Integration Examples​

Express.js Middleware​

import express from 'express';
import { CDPClient } from '@codematic.io/cdp-node';

const app = express();
const cdp = new CDPClient({ cdpApiKey: process.env.CDP_API_KEY });

// Track all page views
app.use((req, res, next) => {
if (req.user) {
cdp.track(req.user.id, 'page_viewed', {
path: req.path,
method: req.method,
user_agent: req.get('user-agent'),
ip: req.ip
}).catch(err => console.error('Tracking error:', err));
}
next();
});

Next.js API Route​

// pages/api/checkout.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { cdpClient } from '@/lib/cdp';

export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { userId, items, total } = req.body;

try {
// Process checkout
const order = await processCheckout(items);

// Track the event
await cdpClient.track(userId, 'checkout_completed', {
order_id: order.id,
total,
item_count: items.length,
payment_method: 'stripe'
});

res.json({ success: true, orderId: order.id });
} catch (error) {
res.status(500).json({ error: error.message });
}
}

Dual-Write Behavior​

When dual-write is enabled, events are sent to both Conviso and Customer.io:

const client = new CDPClient({
cdpApiKey: 'your-cdp-key',
sendToCustomerIo: true,
customerIo: {
siteId: 'your-site-id',
apiKey: 'your-api-key'
}
});

// Sends to both platforms
await client.track('user123', 'purchase_completed', {
amount: 99.99
});