Skip to content

Using InsightEmbed with Express/Node.js ​

This guide explains how to integrate InsightEmbed with Express and Node.js applications, both for serving the widget on your frontend and for interacting with the InsightEmbed API from your backend.

Frontend Integration ​

Serving the Widget in Express ​

In an Express application, you can serve the InsightEmbed widget to your frontend in several ways:

Method 1: Include in HTML Template ​

Add the widget script to your HTML templates (e.g., EJS, Pug, Handlebars):

html
<!-- In your template file (e.g., views/layout.ejs) -->
<!DOCTYPE html>
<html>
<head>
  <title>My Express App</title>
  <!-- Other head elements -->
</head>
<body>
  <%- body %>
  
  <!-- InsightEmbed Widget -->
  <script src="https://cdn.insightembed.com/widget.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', function() {
      InsightEmbed.init({
        apiKey: '<%= process.env.INSIGHT_EMBED_API_KEY %>'
      });
    });
  </script>
</body>
</html>

Method 2: Serve as Static Asset ​

Download the widget script and serve it as a static asset:

javascript
// app.js
const express = require('express');
const app = express();

// Serve static files from 'public' directory
app.use(express.static('public'));

// Your routes
app.get('/', (req, res) => {
  res.render('index', { 
    insightEmbedApiKey: process.env.INSIGHT_EMBED_API_KEY 
  });
});

// Start server
app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Then in your HTML template:

html
<!-- In your template file -->
<script src="/js/insight-embed.js"></script>
<script>
  document.addEventListener('DOMContentLoaded', function() {
    InsightEmbed.init({
      apiKey: '<%= insightEmbedApiKey %>'
    });
  });
</script>

Method 3: Environment Variables with Webpack/Browserify ​

If you're using a bundler like Webpack or Browserify:

javascript
// In your client-side JavaScript file
const apiKey = process.env.INSIGHT_EMBED_API_KEY;

document.addEventListener('DOMContentLoaded', function() {
  const script = document.createElement('script');
  script.src = 'https://cdn.insightembed.com/widget.js';
  script.onload = function() {
    window.InsightEmbed.init({ apiKey });
  };
  document.body.appendChild(script);
});

Make sure to configure your bundler to replace process.env.INSIGHT_EMBED_API_KEY with the actual value during build.

Backend Integration ​

Making API Requests from Node.js ​

You can interact with the InsightEmbed API from your Node.js backend using the official SDK or with HTTP clients like Axios or node-fetch.

Using the Official SDK ​

Install the InsightEmbed Node.js SDK:

bash
npm install @insightembed/node
# or
yarn add @insightembed/node

Use the SDK in your Express routes:

javascript
const express = require('express');
const { InsightEmbed } = require('@insightembed/node');

const app = express();
app.use(express.json());

// Initialize the SDK with your API key
const insightEmbed = new InsightEmbed({
  apiKey: process.env.INSIGHT_EMBED_PRIMARY_API_KEY
});

// Create a route for text analysis
app.post('/api/analyze-text', async (req, res) => {
  try {
    const { text } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }
    
    const result = await insightEmbed.analyzeText({
      text,
      maxTokens: 150
    });
    
    res.json(result);
  } catch (error) {
    console.error('Analysis error:', error);
    res.status(500).json({ 
      error: 'Analysis failed', 
      message: error.message 
    });
  }
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Using Axios ​

If you prefer using Axios:

javascript
const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());

const INSIGHT_EMBED_API_KEY = process.env.INSIGHT_EMBED_PRIMARY_API_KEY;
const API_BASE_URL = 'https://api.insightembed.com/v1';

// Create a route for text analysis
app.post('/api/analyze-text', async (req, res) => {
  try {
    const { text } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }
    
    const response = await axios.post(`${API_BASE_URL}/analyze/text`, {
      text,
      max_tokens: 150
    }, {
      headers: {
        'Authorization': `Bearer ${INSIGHT_EMBED_API_KEY}`,
        'Content-Type': 'application/json'
      }
    });
    
    res.json(response.data);
  } catch (error) {
    console.error('Analysis error:', error.response?.data || error.message);
    res.status(error.response?.status || 500).json({ 
      error: 'Analysis failed', 
      message: error.response?.data?.error?.message || error.message 
    });
  }
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Creating a Proxy Endpoint ​

To protect your API key, you can create a proxy endpoint in your Express app:

javascript
const express = require('express');
const axios = require('axios');
const multer = require('multer');
const upload = multer();

const app = express();
app.use(express.json());

const INSIGHT_EMBED_API_KEY = process.env.INSIGHT_EMBED_PRIMARY_API_KEY;
const API_BASE_URL = 'https://api.insightembed.com/v1';

// Proxy endpoint for text analysis
app.post('/api/proxy/analyze-text', async (req, res) => {
  try {
    const { text, prompt_template, context } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }
    
    const response = await axios.post(`${API_BASE_URL}/analyze/text`, {
      text,
      prompt_template,
      context,
      max_tokens: 150
    }, {
      headers: {
        'Authorization': `Bearer ${INSIGHT_EMBED_API_KEY}`,
        'Content-Type': 'application/json'
      }
    });
    
    res.json(response.data);
  } catch (error) {
    console.error('Analysis error:', error.response?.data || error.message);
    res.status(error.response?.status || 500).json({ 
      error: 'Analysis failed', 
      message: error.response?.data?.error?.message || error.message 
    });
  }
});

// Proxy endpoint for image analysis (with file upload)
app.post('/api/proxy/analyze-image', upload.single('image'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'Image file is required' });
    }
    
    const formData = new FormData();
    formData.append('image', req.file.buffer, {
      filename: req.file.originalname,
      contentType: req.file.mimetype
    });
    
    if (req.body.prompt_template) {
      formData.append('prompt_template', req.body.prompt_template);
    }
    
    if (req.body.context) {
      formData.append('context', req.body.context);
    }
    
    const response = await axios.post(`${API_BASE_URL}/analyze/image`, formData, {
      headers: {
        'Authorization': `Bearer ${INSIGHT_EMBED_API_KEY}`,
        'Content-Type': 'multipart/form-data'
      }
    });
    
    res.json(response.data);
  } catch (error) {
    console.error('Image analysis error:', error.response?.data || error.message);
    res.status(error.response?.status || 500).json({ 
      error: 'Image analysis failed', 
      message: error.response?.data?.error?.message || error.message 
    });
  }
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Securing Your API Key ​

Environment Variables ​

Store your API key in environment variables:

bash
# .env file
INSIGHT_EMBED_WIDGET_API_KEY=your_widget_api_key
INSIGHT_EMBED_PRIMARY_API_KEY=your_primary_api_key

Load them with dotenv:

javascript
// At the top of your app.js
require('dotenv').config();

// Then use them
const widgetApiKey = process.env.INSIGHT_EMBED_WIDGET_API_KEY;
const primaryApiKey = process.env.INSIGHT_EMBED_PRIMARY_API_KEY;

API Key Validation ​

Implement middleware to validate requests to your proxy endpoints:

javascript
const validateApiRequest = (req, res, next) => {
  // Get the origin or referer
  const origin = req.headers.origin || req.headers.referer;
  
  // Check if the request is coming from an allowed domain
  const allowedDomains = ['https://yourdomain.com', 'https://www.yourdomain.com'];
  
  if (!origin || !allowedDomains.some(domain => origin.startsWith(domain))) {
    return res.status(403).json({ error: 'Unauthorized domain' });
  }
  
  next();
};

// Use the middleware
app.post('/api/proxy/analyze-text', validateApiRequest, async (req, res) => {
  // Your code here
});

Rate Limiting ​

Implement rate limiting to prevent abuse of your proxy endpoints:

javascript
const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP, please try again after 15 minutes'
});

// Apply to all requests to proxy endpoints
app.use('/api/proxy/', apiLimiter);

Caching Responses ​

Implement caching to improve performance and reduce API calls:

javascript
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 600 }); // Cache for 10 minutes

app.post('/api/proxy/analyze-text', async (req, res) => {
  try {
    const { text } = req.body;
    
    // Create a cache key based on the request
    const cacheKey = `text_analysis_${Buffer.from(text).toString('base64')}`;
    
    // Check if we have a cached response
    const cachedResponse = cache.get(cacheKey);
    if (cachedResponse) {
      return res.json(cachedResponse);
    }
    
    // Proceed with the API call
    const response = await axios.post(/* ... */);
    
    // Cache the response
    cache.set(cacheKey, response.data);
    
    res.json(response.data);
  } catch (error) {
    // Error handling
  }
});

Webhook Integration ​

Set up a webhook endpoint to receive notifications from InsightEmbed:

javascript
app.post('/api/webhooks/insight-embed', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-insight-embed-signature'];
  
  // Verify the webhook signature
  const isValid = verifyWebhookSignature(
    req.body,
    signature,
    process.env.INSIGHT_EMBED_WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(400).send('Invalid signature');
  }
  
  const event = JSON.parse(req.body);
  
  // Handle different event types
  switch (event.type) {
    case 'quota.exceeded':
      console.log('Quota exceeded:', event.data);
      // Notify administrators or update database
      break;
    case 'analysis.completed':
      console.log('Analysis completed:', event.data);
      // Process or store the analysis result
      break;
    default:
      console.log('Unknown event type:', event.type);
  }
  
  res.status(200).send('Webhook received');
});

// Helper function to verify webhook signatures
function verifyWebhookSignature(payload, signature, secret) {
  const crypto = require('crypto');
  const hmac = crypto.createHmac('sha256', secret);
  const digest = hmac.update(payload).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(digest),
    Buffer.from(signature)
  );
}

Best Practices ​

  1. API Key Security: Never expose your Primary API Key in client-side code. Use environment variables and proxy endpoints.

  2. Error Handling: Implement comprehensive error handling for all API interactions.

  3. Rate Limiting: Apply rate limiting to prevent abuse of your proxy endpoints.

  4. Caching: Implement caching for repeated analysis requests to improve performance.

  5. Logging: Set up proper logging for debugging and monitoring API usage.

  6. Validation: Validate all user inputs before sending them to the InsightEmbed API.

  7. CORS: Configure CORS properly to restrict which domains can access your proxy endpoints.

Example: Complete Express Application ​

Here's a complete example of an Express application with InsightEmbed integration:

javascript
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const multer = require('multer');
const rateLimit = require('express-rate-limit');
const NodeCache = require('node-cache');
const cors = require('cors');
const path = require('path');

const app = express();
const upload = multer();
const cache = new NodeCache({ stdTTL: 600 });

// Middleware
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'ejs');

// CORS configuration
app.use(cors({
  origin: ['https://yourdomain.com', 'https://www.yourdomain.com'],
  methods: ['GET', 'POST'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

// Rate limiting
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,
  message: 'Too many requests from this IP, please try again after 15 minutes'
});
app.use('/api/proxy/', apiLimiter);

// Constants
const INSIGHT_EMBED_API_KEY = process.env.INSIGHT_EMBED_PRIMARY_API_KEY;
const WIDGET_API_KEY = process.env.INSIGHT_EMBED_WIDGET_API_KEY;
const API_BASE_URL = 'https://api.insightembed.com/v1';

// Routes
app.get('/', (req, res) => {
  res.render('index', { widgetApiKey: WIDGET_API_KEY });
});

// Proxy endpoint for text analysis
app.post('/api/proxy/analyze-text', async (req, res) => {
  try {
    const { text, prompt_template, context } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }
    
    // Create a cache key
    const cacheKey = `text_analysis_${Buffer.from(JSON.stringify(req.body)).toString('base64')}`;
    
    // Check cache
    const cachedResponse = cache.get(cacheKey);
    if (cachedResponse) {
      return res.json(cachedResponse);
    }
    
    const response = await axios.post(`${API_BASE_URL}/analyze/text`, {
      text,
      prompt_template,
      context,
      max_tokens: 150
    }, {
      headers: {
        'Authorization': `Bearer ${INSIGHT_EMBED_API_KEY}`,
        'Content-Type': 'application/json'
      }
    });
    
    // Cache the response
    cache.set(cacheKey, response.data);
    
    res.json(response.data);
  } catch (error) {
    console.error('Analysis error:', error.response?.data || error.message);
    res.status(error.response?.status || 500).json({ 
      error: 'Analysis failed', 
      message: error.response?.data?.error?.message || error.message 
    });
  }
});

// Proxy endpoint for image analysis
app.post('/api/proxy/analyze-image', upload.single('image'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'Image file is required' });
    }
    
    const formData = new FormData();
    formData.append('image', req.file.buffer, {
      filename: req.file.originalname,
      contentType: req.file.mimetype
    });
    
    if (req.body.prompt_template) {
      formData.append('prompt_template', req.body.prompt_template);
    }
    
    if (req.body.context) {
      formData.append('context', req.body.context);
    }
    
    const response = await axios.post(`${API_BASE_URL}/analyze/image`, formData, {
      headers: {
        'Authorization': `Bearer ${INSIGHT_EMBED_API_KEY}`,
        'Content-Type': 'multipart/form-data'
      }
    });
    
    res.json(response.data);
  } catch (error) {
    console.error('Image analysis error:', error.response?.data || error.message);
    res.status(error.response?.status || 500).json({ 
      error: 'Image analysis failed', 
      message: error.response?.data?.error?.message || error.message 
    });
  }
});

// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

And the corresponding EJS template:

html
<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<head>
  <title>InsightEmbed Demo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { font-family: Arial, sans-serif; line-height: 1.6; padding: 20px; }
    .container { max-width: 800px; margin: 0 auto; }
    h1 { color: #333; }
  </style>
</head>
<body>
  <div class="container">
    <h1>InsightEmbed Demo</h1>
    <p>This page demonstrates the InsightEmbed widget integration with Express.</p>
    
    <div id="custom-widget-container"></div>
  </div>
  
  <!-- InsightEmbed Widget -->
  <script src="https://cdn.insightembed.com/widget.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', function() {
      InsightEmbed.init({
        apiKey: '<%= widgetApiKey %>',
        position: {
          anchor: 'bottom-right',
          horizontalOffset: 20,
          verticalOffset: 20
        },
        theme: {
          primaryColor: '#0F766E',
          backgroundColor: '#F8FAFC',
          textColor: '#334155'
        },
        branding: {
          buttonLabel: 'Analyze Content',
          panelTitle: 'Content Analysis'
        }
      });
    });
  </script>
</body>
</html>