Express.js Proxy Setup
Configure Express.js middleware to proxy AddonPulse tracking requests
Express.js makes it easy to proxy AddonPulse tracking using middleware. This guide shows how to set up a reverse proxy using http-proxy-middleware.
Overview
The http-proxy-middleware package provides a simple way to proxy requests in Express applications, making it perfect for routing analytics requests to AddonPulse servers.
What you'll achieve:
- Proxy all AddonPulse endpoints through your Express app
- Forward necessary headers for accurate tracking
- Optional caching for better performance
- Support all AddonPulse features
Prerequisites
- Node.js and Express.js application
- npm or yarn package manager
- Your AddonPulse instance URL
https://app.addonpulse.com - Your AddonPulse site ID
Implementation
Install http-proxy-middleware
Install the proxy middleware package:
npm install http-proxy-middlewareOr with yarn:
yarn add http-proxy-middlewareConfigure Environment Variables
Create or update your .env file:
# .env
ADDONPULSE_HOST=https://app.addonpulse.comInstall dotenv if not already: npm install dotenv
Add Proxy Middleware to Express
Add to your Express server file (e.g., server.js or app.js):
// server.js
require('dotenv').config();
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const ADDONPULSE_HOST = process.env.ADDONPULSE_HOST || 'https://app.addonpulse.com';
// AddonPulse Analytics Proxy
// Proxy all /analytics/* requests to AddonPulse
app.use('/analytics', createProxyMiddleware({
target: ADDONPULSE_HOST,
changeOrigin: true,
pathRewrite: {
'^/analytics': '/api', // Rewrite /analytics/script.js to /api/script.js
},
onProxyReq: (proxyReq, req, res) => {
// Forward client IP for accurate geolocation
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Forwarded-For', clientIp);
proxyReq.setHeader('X-Real-IP', clientIp);
},
logLevel: 'warn',
}));
// Exception for site config endpoint (different path structure)
app.use('/analytics/site/tracking-config', createProxyMiddleware({
target: ADDONPULSE_HOST,
changeOrigin: true,
pathRewrite: {
'^/analytics/site': '/api/site', // Rewrite to /api/site/tracking-config
},
onProxyReq: (proxyReq, req, res) => {
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Forwarded-For', clientIp);
proxyReq.setHeader('X-Real-IP', clientIp);
},
}));
// Your other routes
app.get('/', (req, res) => {
res.send('Hello World');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});Minimal setup with basic tracking:
// server.js
require('dotenv').config();
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const ADDONPULSE_HOST = process.env.ADDONPULSE_HOST || 'https://app.addonpulse.com';
// Proxy script and track endpoints only
app.use(['/analytics/script.js', '/analytics/track'], createProxyMiddleware({
target: ADDONPULSE_HOST,
changeOrigin: true,
pathRewrite: {
'^/analytics': '/api',
},
onProxyReq: (proxyReq, req, res) => {
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Forwarded-For', clientIp);
proxyReq.setHeader('X-Real-IP', clientIp);
},
}));
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});For TypeScript projects:
// server.ts
import 'dotenv/config';
import express, { Request, Response } from 'express';
import { createProxyMiddleware, Options } from 'http-proxy-middleware';
const app = express();
const ADDONPULSE_HOST = process.env.ADDONPULSE_HOST || 'https://app.addonpulse.com';
const proxyOptions: Options = {
target: ADDONPULSE_HOST,
changeOrigin: true,
pathRewrite: {
'^/analytics': '/api',
},
onProxyReq: (proxyReq, req, res) => {
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Forwarded-For', clientIp as string);
proxyReq.setHeader('X-Real-IP', clientIp as string);
},
logLevel: 'warn',
};
app.use('/analytics', createProxyMiddleware(proxyOptions));
app.use('/analytics/site/tracking-config', createProxyMiddleware({
target: ADDONPULSE_HOST,
changeOrigin: true,
pathRewrite: {
'^/analytics/site': '/api/site',
},
onProxyReq: proxyOptions.onProxyReq,
}));
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});Update Your Tracking Script
In your HTML or template files:
<script src="/analytics/script.js" async data-site-id="YOUR_SITE_ID"></script>Start Your Server
node server.jsOr with nodemon for development:
npm install -D nodemon
npx nodemon server.jsVerify the Setup
-
Test script endpoint:
curl -I http://localhost:3000/analytics/script.js -
Open your app in a browser with Developer Tools
-
Check Network tab: Requests should go to
/analytics/* -
Verify in AddonPulse dashboard: Data should appear
How It Works
The http-proxy-middleware intercepts requests matching the specified paths and forwards them to AddonPulse:
- Request to
/analytics/script.jsis intercepted - Path is rewritten to
/api/script.js - Request is forwarded to
https://app.addonpulse.com/api/script.js - Client IP headers are added for accurate tracking
- Response is sent back to the browser
Advanced Configuration
Caching Responses
Add caching for better performance:
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 3600 }); // 1 hour default
// Install: npm install node-cache
// Caching middleware for scripts
const cacheMiddleware = (req, res, next) => {
const key = req.originalUrl;
const cachedResponse = cache.get(key);
if (cachedResponse) {
res.set('X-Cache-Status', 'HIT');
return res.send(cachedResponse);
}
// Store original send
const originalSend = res.send.bind(res);
res.send = (body) => {
cache.set(key, body);
res.set('X-Cache-Status', 'MISS');
return originalSend(body);
};
next();
};
// Apply caching only to script files
app.use('/analytics/script.js', cacheMiddleware);
app.use('/analytics/script.js', createProxyMiddleware({
// ... proxy config
}));Rate Limiting
Protect your proxy with rate limiting:
const rateLimit = require('express-rate-limit');
// Install: npm install express-rate-limit
const analyticsLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100, // Limit each IP to 100 requests per minute
message: 'Too many requests from this IP',
standardHeaders: true,
legacyHeaders: false,
});
// Apply to tracking endpoints
app.use('/analytics/track', analyticsLimiter);
app.use('/analytics/track', createProxyMiddleware({
// ... proxy config
}));Error Handling
Add error handling for proxy failures:
app.use('/analytics', createProxyMiddleware({
target: ADDONPULSE_HOST,
changeOrigin: true,
pathRewrite: {
'^/analytics': '/api',
},
onError: (err, req, res) => {
console.error('Proxy error:', err);
res.status(500).json({ error: 'Analytics proxy error' });
},
onProxyReq: (proxyReq, req, res) => {
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Forwarded-For', clientIp);
proxyReq.setHeader('X-Real-IP', clientIp);
},
}));CORS Configuration
If serving API endpoints to other domains:
const cors = require('cors');
// Install: npm install cors
app.use('/analytics', cors({
origin: ['https://yourdomain.com', 'https://www.yourdomain.com'],
credentials: true,
}));
app.use('/analytics', createProxyMiddleware({
// ... proxy config
}));Troubleshooting
Requests timing out
Problem: Proxy requests hang or timeout.
Solution: Increase timeout limits:
app.use('/analytics', createProxyMiddleware({
target: ADDONPULSE_HOST,
changeOrigin: true,
timeout: 30000, // 30 seconds
proxyTimeout: 30000,
pathRewrite: {
'^/analytics': '/api',
},
}));Incorrect geolocation
Problem: All visitors show server's location.
Solution: Ensure IP forwarding is configured:
onProxyReq: (proxyReq, req, res) => {
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Forwarded-For', clientIp);
proxyReq.setHeader('X-Real-IP', clientIp);
}Path rewriting issues
Problem: 404 errors on AddonPulse endpoints.
Solution: Check path rewriting is correct:
pathRewrite: {
'^/analytics': '/api', // /analytics/script.js → /api/script.js
}Debug by logging:
onProxyReq: (proxyReq, req, res) => {
console.log('Proxying:', req.method, req.path, '→', proxyReq.path);
}Related Resources
- Tracking Script Documentation - Script configuration
- Generic Proxy Guide - Core concepts
- http-proxy-middleware docs - Middleware documentation