7 min de lectura
Express.js Quickstart
Get up and running with Zenovay analytics in your Express.js application in under 5 minutes.
Two Integration Approaches
Express.js apps typically need both:
- Client-side tracking - Add the Zenovay script tag to your HTML templates for automatic page view and visitor tracking
- Server-side event tracking - Use direct API calls from your Express routes to track backend events
Client-Side Tracking
Add the Zenovay script to your HTML templates:
<!-- views/layout.ejs or views/base.pug -->
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<!-- Zenovay Analytics -->
<script defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js">
</script>
</head>
<body>
<%- body %>
</body>
</html>
Server-Side Event Tracking
For server-side tracking in Express.js, use the Zenovay External API directly with fetch. No npm package is needed.
1. Create a Helper Module
// lib/zenovay.js
const ZENOVAY_API_URL = 'https://api.zenovay.com/api/external/v1';
const ZENOVAY_API_KEY = process.env.ZENOVAY_API_KEY;
async function trackEvent(event, properties = {}, userId = null) {
try {
await fetch(`${ZENOVAY_API_URL}/events`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': ZENOVAY_API_KEY,
},
body: JSON.stringify({
event,
userId,
properties,
timestamp: new Date().toISOString(),
}),
});
} catch (error) {
console.error('Zenovay tracking error:', error.message);
}
}
async function identifyUser(userId, traits = {}) {
try {
await fetch(`${ZENOVAY_API_URL}/identify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': ZENOVAY_API_KEY,
},
body: JSON.stringify({
userId,
traits,
timestamp: new Date().toISOString(),
}),
});
} catch (error) {
console.error('Zenovay identify error:', error.message);
}
}
module.exports = { trackEvent, identifyUser };
2. Use in Your Express Routes
// routes/signup.js
const express = require('express');
const router = express.Router();
const { trackEvent, identifyUser } = require('../lib/zenovay');
router.post('/signup', async (req, res) => {
const { email, name, plan } = req.body;
try {
// Create user account
const user = await createUser({ email, name, plan });
// Track signup event
await trackEvent('signup_completed', {
plan: plan,
email: email,
source: 'website'
}, user.id);
res.json({ success: true, user });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
module.exports = router;
Environment Variables
Create a .env file:
# .env
ZENOVAY_API_KEY=your_api_key_here
ZENOVAY_TRACKING_CODE=your_site_id_here
PORT=3000
Load environment variables:
// At the top of your app.js
require('dotenv').config();
Middleware for User Tracking
Create middleware to identify users:
// middleware/analytics.js
const { identifyUser } = require('../lib/zenovay');
module.exports = function analyticsMiddleware(req, res, next) {
// Identify logged-in users
if (req.user) {
identifyUser(req.user.id, {
email: req.user.email,
name: req.user.name,
plan: req.user.subscription?.plan,
createdAt: req.user.createdAt
});
}
next();
};
// Use in app.js
const analyticsMiddleware = require('./middleware/analytics');
app.use(analyticsMiddleware);
Common Use Cases
Track API Requests
const { trackEvent } = require('../lib/zenovay');
// Track API endpoint usage
app.post('/api/generate', async (req, res) => {
const { userId, model, prompt } = req.body;
try {
const result = await generateContent(model, prompt);
// Track API usage
await trackEvent('api_request', {
endpoint: '/api/generate',
model: model,
success: true,
responseTime: result.time
}, userId);
res.json(result);
} catch (error) {
await trackEvent('api_error', {
endpoint: '/api/generate',
error: error.message
}, userId);
res.status(500).json({ error: error.message });
}
});
Track User Actions
const { trackEvent } = require('../lib/zenovay');
// Track purchases
router.post('/checkout', async (req, res) => {
const { userId, cartItems, total } = req.body;
try {
const order = await createOrder({ userId, cartItems, total });
// Track purchase
await trackEvent('purchase_completed', {
orderId: order.id,
revenue: total,
currency: 'USD',
items: cartItems.map(item => ({
productId: item.id,
quantity: item.quantity,
price: item.price
}))
}, userId);
res.json({ success: true, order });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
Track Authentication
const { trackEvent, identifyUser } = require('../lib/zenovay');
// Track login
router.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
const user = await authenticateUser(email, password);
// Identify user
await identifyUser(user.id, {
email: user.email,
name: user.name,
lastLogin: new Date().toISOString()
});
// Track login event
await trackEvent('user_logged_in', {
method: 'password',
ip: req.ip
}, user.id);
res.json({ success: true, user });
} catch (error) {
res.status(401).json({ error: 'Invalid credentials' });
}
});
Error Tracking
Track errors globally:
const { trackEvent } = require('../lib/zenovay');
// Error handling middleware
app.use((error, req, res, next) => {
console.error(error);
// Track error
trackEvent('server_error', {
error: error.message,
stack: error.stack,
path: req.path,
method: req.method
}, req.user?.id).catch(err => console.error('Analytics error:', err));
res.status(500).json({ error: 'Internal server error' });
});
TypeScript Support
For TypeScript projects, create typed helper functions:
// lib/zenovay.ts
const ZENOVAY_API_URL = 'https://api.zenovay.com/api/external/v1';
const ZENOVAY_API_KEY = process.env.ZENOVAY_API_KEY!;
interface TrackEventOptions {
event: string;
userId?: string;
properties?: Record<string, unknown>;
}
interface IdentifyOptions {
userId: string;
traits: Record<string, unknown>;
}
export async function trackEvent(
event: string,
properties: Record<string, unknown> = {},
userId?: string
): Promise<void> {
try {
await fetch(`${ZENOVAY_API_URL}/events`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': ZENOVAY_API_KEY,
},
body: JSON.stringify({
event,
userId,
properties,
timestamp: new Date().toISOString(),
}),
});
} catch (error) {
console.error('Zenovay tracking error:', error);
}
}
export async function identifyUser(
userId: string,
traits: Record<string, unknown> = {}
): Promise<void> {
try {
await fetch(`${ZENOVAY_API_URL}/identify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': ZENOVAY_API_KEY,
},
body: JSON.stringify({
userId,
traits,
timestamp: new Date().toISOString(),
}),
});
} catch (error) {
console.error('Zenovay identify error:', error);
}
}
// app.ts
import express from 'express';
import { trackEvent } from './lib/zenovay';
const app = express();
// Type-safe tracking
app.post('/api/action', async (req, res) => {
await trackEvent('action_performed', {
actionType: 'purchase',
amount: 99.99
}, req.user?.id);
res.json({ success: true });
});
Testing
Mock the fetch calls in your tests:
// __tests__/routes/signup.test.js
const request = require('supertest');
const app = require('../app');
// Mock fetch for Zenovay API calls
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({}),
});
describe('POST /signup', () => {
it('should track signup event', async () => {
const response = await request(app)
.post('/signup')
.send({ email: '[email protected]', plan: 'pro' });
expect(response.status).toBe(200);
expect(global.fetch).toHaveBeenCalledWith(
expect.stringContaining('/events'),
expect.objectContaining({
method: 'POST',
body: expect.stringContaining('signup_completed')
})
);
});
});
Complete Example
Here's a complete Express app with Zenovay:
// app.js
require('dotenv').config();
const express = require('express');
const app = express();
// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Zenovay helper
const ZENOVAY_API_URL = 'https://api.zenovay.com/api/external/v1';
const ZENOVAY_API_KEY = process.env.ZENOVAY_API_KEY;
async function trackEvent(event, properties = {}, userId = null) {
try {
await fetch(`${ZENOVAY_API_URL}/events`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': ZENOVAY_API_KEY,
},
body: JSON.stringify({ event, userId, properties }),
});
} catch (error) {
console.error('Zenovay error:', error.message);
}
}
async function identifyUser(userId, traits = {}) {
try {
await fetch(`${ZENOVAY_API_URL}/identify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': ZENOVAY_API_KEY,
},
body: JSON.stringify({ userId, traits }),
});
} catch (error) {
console.error('Zenovay error:', error.message);
}
}
// Routes
app.post('/api/signup', async (req, res) => {
try {
const user = await createUser(req.body);
await trackEvent('user_signup', {
plan: req.body.plan,
source: 'web'
}, user.id);
res.json({ success: true, user });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/api/login', async (req, res) => {
try {
const user = await authenticateUser(req.body);
await identifyUser(user.id, {
email: user.email,
name: user.name
});
res.json({ success: true, user });
} catch (error) {
res.status(401).json({ error: 'Invalid credentials' });
}
});
// Error handler
app.use((error, req, res, next) => {
trackEvent('error', {
message: error.message,
path: req.path
}).catch(console.error);
res.status(500).json({ error: 'Internal error' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
module.exports = app;
Next Steps
- API Reference - Full API documentation
- Custom Events - Learn about event tracking
- Node.js Quickstart - Complete Node.js guide
- Vanilla JS Example - Client-side tracking
Getting Help
- Documentation: docs.zenovay.com
- Support: [email protected]
- GitHub: github.com/zenovay
¿Fue útil esta página?