メインコンテンツへスキップ
7分で読めます

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:

  1. Client-side tracking - Add the Zenovay script tag to your HTML templates for automatic page view and visitor tracking
  2. 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

Getting Help

このページは役に立ちましたか?