Production Facebook Messenger AI Sales Bot Webhook Server in Node.js / Express | Sajedar E-Commerce Automation A developer published a Node.js/Express webhook server for a Facebook Messenger AI sales bot aimed at e-commerce pages, implementing Meta Graph API verification, messaging event handling, and quick-reply dispatch within Meta's 20-second acknowledgement window. The code includes signature-ready raw body capture, a Send API helper targeting Graph API v19.0, and keyword-triggered replies with Nepali-language price handling. | | / | | | 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 ; |