MongoDB's flexible document model is a natural fit for webhook data - no schema migrations needed when InstantDM adds new event fields. Store the entire webhook payload as-is and query it with MongoDB's powerful aggregation pipeline.
Setup
npm install express mongodb dotenv
Webhook Receiver
const express = require('express');
const { MongoClient } = require('mongodb');
const app = express();
app.use(express.json());
const client = new MongoClient(process.env.MONGODB_URI);
let db;
async function connect() {
await client.connect();
db = client.db('instantdm');
console.log('Connected to MongoDB');
}
app.post('/webhook', async (req, res) => {
const { event, timestamp, data } = req.body;
try {
await db.collection('events').insertOne({
event_type: event,
timestamp: new Date(timestamp),
username: data.username,
instagram_user_id: data.instagram_user_id,
flow_name: data.flow_name || null,
lead_data: data.response_variables || null,
comment_text: data.comment_text || null,
message_text: data.message_text || null,
post_url: data.post_url || null,
raw: req.body,
created_at: new Date(),
});
res.status(200).json({ status: 'inserted' });
} catch (error) {
console.error('Insert error:', error);
res.status(500).json({ status: 'error' });
}
});
connect().then(() => app.listen(3000));
Useful Queries
// Leads today
db.collection('events').find({
event_type: 'flow_completed',
timestamp: { $gte: new Date(new Date().setHours(0, 0, 0, 0)) },
}).toArray();
// Leads per flow
db.collection('events').aggregate([
{ $match: { event_type: 'flow_completed' } },
{ $group: { _id: '$flow_name', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
]).toArray();
// Unique leads by email
db.collection('events').aggregate([
{ $match: { 'lead_data.email': { $exists: true } } },
{ $group: { _id: '$lead_data.email', latest: { $last: '$$ROOT' } } },
]).toArray();
Indexes
db.collection('events').createIndex({ event_type: 1, timestamp: -1 });
db.collection('events').createIndex({ username: 1 });
db.collection('events').createIndex({ 'lead_data.email': 1 });
Hosting Options
- MongoDB Atlas - free tier with 512MB storage
- Railway - managed MongoDB
- Self-hosted - Docker or bare metal
What's Next
- Set up PostgreSQL if you prefer relational databases.
- Connect to Firebase for real-time sync.
- Build Custom Dashboards on top of your data.
- Explore the full API docs at instantdm.com/instagram-api-docs.