# Production Facebook Messenger AI Sales Bot Webhook Server in Node.js / Express | Sajedar E-Commerce Automation

> Source: <https://gist.github.com/Dimanjan/875ba9ea9c1af0f2047e08e134efb785>
> Published: 2026-09-18 15:38:28+00:00

|  | /** | 
|  | * Production Facebook Messenger Webhook Server | 
|  | * Implements Meta Graph API Verification, Messaging Event Receiver, | 
|  | * and 2-second Quick Reply Dispatch for E-commerce Pages. | 
|  | * | 
|  | * 📖 Complete Tutorial & Setup Guide: | 
|  | * https://www.sajedar.com/tutorials/facebook-messenger-chatbot-ecommerce | 
|  | * | 
|  | * 🤖 Full AI Sales Agent Capabilities in Nepal: | 
|  | * https://www.sajedar.com/facebook-messenger-ai-chatbot-nepal | 
|  | * | 
|  | * 🛠️ Messenger JSON Payload Builder Tool: | 
|  | * https://www.sajedar.com/tools/messenger-json-builder | 
|  | */ | 
|  |  | 
|  | const express = require('express'); | 
|  | const crypto = require('crypto'); | 
|  | const app = express(); | 
|  |  | 
|  | app.use(express.json({ | 
|  | verify: (req, res, buf) => { | 
|  | req.rawBody = buf; | 
|  | } | 
|  | })); | 
|  |  | 
|  | const PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN; | 
|  | const VERIFY_TOKEN = process.env.VERIFY_TOKEN; | 
|  | const APP_SECRET = process.env.APP_SECRET; | 
|  |  | 
|  | // 1. Meta Webhook Verification Endpoint (GET) | 
|  | app.get('/webhook', (req, res) => { | 
|  | const mode = req.query['hub.mode']; | 
|  | const token = req.query['hub.verify_token']; | 
|  | const challenge = req.query['hub.challenge']; | 
|  |  | 
|  | if (mode === 'subscribe' && token === VERIFY_TOKEN) { | 
|  | console.log('✅ Webhook verified by Meta Graph API'); | 
|  | res.status(200).send(challenge); | 
|  | } else { | 
|  | res.sendStatus(403); | 
|  | } | 
|  | }); | 
|  |  | 
|  | // 2. Message Event Receiver (POST) | 
|  | app.post('/webhook', (req, res) => { | 
|  | const body = req.body; | 
|  |  | 
|  | if (body.object === 'page') { | 
|  | body.entry.forEach(entry => { | 
|  | const webhookEvent = entry.messaging?.[0]; | 
|  | if (!webhookEvent) return; | 
|  |  | 
|  | const senderPsid = webhookEvent.sender.id; | 
|  |  | 
|  | if (webhookEvent.message) { | 
|  | handleIncomingMessage(senderPsid, webhookEvent.message); | 
|  | } else if (webhookEvent.postback) { | 
|  | handlePostback(senderPsid, webhookEvent.postback); | 
|  | } | 
|  | }); | 
|  |  | 
|  | // Acknowledge receipt within 20 seconds to prevent Meta retries | 
|  | res.status(200).send('EVENT_RECEIVED'); | 
|  | } else { | 
|  | res.sendStatus(404); | 
|  | } | 
|  | }); | 
|  |  | 
|  | // Send Message API helper | 
|  | async function callSendAPI(senderPsid, responsePayload) { | 
|  | const url = 'https://graph.facebook.com/v19.0/me/messages?access_token=' + PAGE_ACCESS_TOKEN; | 
|  |  | 
|  | try { | 
|  | const res = await fetch(url, { | 
|  | method: 'POST', | 
|  | headers: { 'Content-Type': 'application/json' }, | 
|  | body: JSON.stringify({ | 
|  | recipient: { id: senderPsid }, | 
|  | messaging_type: 'RESPONSE', | 
|  | message: responsePayload | 
|  | }) | 
|  | }); | 
|  | const data = await res.json(); | 
|  | return data; | 
|  | } catch (err) { | 
|  | console.error('Error calling Send API:', err); | 
|  | } | 
|  | } | 
|  |  | 
|  | async function handleIncomingMessage(senderPsid, receivedMessage) { | 
|  | const text = receivedMessage.text?.toLowerCase() \|\| ''; | 
|  |  | 
|  | // Handle Quick Inquiries | 
|  | if (text.includes('price') \|\| text.includes('kati ho') \|\| text.includes('cost')) { | 
|  | await callSendAPI(senderPsid, { | 
|  | text: 'Namaste! 🙏 Our bestsellers start at Rs. 1,499 with free delivery inside Kathmandu Valley. Would you like to see available colors or sizes?', | 
|  | quick_replies: [ | 
|  | { content_type: 'text', title: '👗 View Catalog', payload: 'VIEW_CATALOG' }, | 
|  | { content_type: 'text', title: '📍 Delivery Info', payload: 'DELIVERY_INFO' }, | 
|  | { content_type: 'text', title: '💬 Human Agent', payload: 'TALK_HUMAN' } | 
|  | ] | 
|  | }); | 
|  | } else { | 
|  | await callSendAPI(senderPsid, { | 
|  | text: 'Thank you for reaching out! How can we help your shopping today?' | 
|  | }); | 
|  | } | 
|  | } | 
|  |  | 
|  | const PORT = process.env.PORT \|\| 3000; | 
|  | app.listen(PORT, () => console.log('Messenger Webhook running on port ' + PORT)); |
