- THIS IS NOT A PRODUCTION READY THING. IT IS JUST TO UNDERSTAND THE FLOW OF WORK AND JUST FOR EDUCATIONAL PURPOSE. DO NOT TRY THIS IN PRODUCTS AS IT MAY CAUSE SOME SERIOUS ISSUES TO THE CLIENT SITE OR SHOPIFY ECOSYSTEM. FOR THE PRODUCTION WE NEED PROPER AUTHENTICATION PROCCESS OF STORES AND OTHER HMAC VALUES AND MAINTAIN PROPER SESSIONS FOR THE CLINTS AND ACTIVITIES.
- DO NOT MISUSE IT. IT'S JUST FOR EDUCATIONAL PURPOSE JUST TO UNDERSTAND THE FLOW.
- AUTHOR: StackWise Dev
This project is a simple Node.js server that:
- connects to Shopify Admin API
- registers webhooks
- receives webhook events
- verifies webhook HMAC signature
- saves fetched data in a local JSON database
The flow below is based on server.js logic (starting after line 18 comments).
- Uses
SHOPIFY_ACCESS_TOKENto call Shopify Admin API. - Creates and lists store webhooks.
- Receives product update webhook data at a local endpoint.
- Verifies webhook source using
x-shopify-hmac-sha256. - Fetches products and orders from Shopify and stores them in
database/db.json.
- Node.js + Express
dotenvfor env variableslowdbfor lightweight local storagecryptofor HMAC verification
Create/update .env.webhook-learning:
PORT=3000
BASE_URL=http://localhost:3000
SHOPIFY_API_KEY=your_client_id
SHOPIFY_API_SECRET=your_client_secret
SHOPIFY_ACCESS_TOKEN=your_admin_api_access_token
SHOPIFY_STORE_URL=https://your-store.myshopify.com
SCOPES=read_products,write_products,read_orders,write_ordersNotes:
SHOPIFY_ACCESS_TOKENis required for Admin API calls.SHOPIFY_API_SECRETis required for webhook HMAC verification.
npm install
npm startServer starts at:
http://localhost:3000
On startup:
.env.webhook-learningis loaded.- Express app is created.
- Raw parser is enabled for
/api/webhook/*routes. - JSON parser is enabled for normal API routes.
database/db.jsonis initialized with:products: []orders: []webhooks: []
Endpoint:
POST /api/shop/register-webhook
Body example:
{
"topic": "products/update",
"address": "https://your-public-url.com/api/webhook/product-update",
"format": "json"
}What happens:
- Validates
topic,address,format. - Checks local DB to avoid duplicate topic registration.
- Calls Shopify:
POST {SHOPIFY_STORE_URL}/admin/api/2026-04/webhooks.json- Header:
X-Shopify-Access-Token
- Saves webhook response in
db.json.
Endpoint:
GET /api/shop/webhooks
Purpose:
- Fetch all registered webhooks from Shopify store.
Webhook receiver:
POST /api/webhook/product-update
This route:
- verifies HMAC using
SHOPIFY_API_SECRET - rejects invalid source with
401 - parses webhook payload from raw body buffer
- logs payload info and returns success
For webhook verification, Shopify signs the raw request body. If body is parsed into object before verification, HMAC check fails.
That is why this project uses:
express.raw({ type: "application/json" })on/api/webhook/*routes.
GET /api/shop/products
GET /api/shop/orders
Both endpoints:
- call Shopify Admin API with
X-Shopify-Access-Token - save result to
database/db.json
- Add env values in
.env.webhook-learning. - Run server with
npm start. - Register webhook using
POST /api/shop/register-webhook. - Trigger a product update in Shopify admin.
- Check server logs for webhook payload.
- Call
GET /api/shop/productsandGET /api/shop/orders. - Open
database/db.jsonto confirm saved data.
-
401 Unauthorizedduring register:- Check
SHOPIFY_ACCESS_TOKENvalue. - Ensure app is installed on same store.
- Ensure
SHOPIFY_STORE_URLis correct.
- Check
-
Webhook HMAC validation fails:
- Confirm
SHOPIFY_API_SECRETmatches the app secret. - Ensure webhook route receives raw body (Buffer).
- Confirm
-
Webhook not delivered:
- Ensure webhook
addressis publicly reachable HTTPS URL. - Confirm topic is correct (
products/update, etc.).
- Ensure webhook
- Never commit
.env.webhook-learning. - Rotate API secret/token if exposed.
- Keep HMAC verification enabled for every webhook route.