menu-MENAmenu-MENA
HomePricingBlogContact UsGet Started
Promo codes admin table with three example codes: LASTONE at 25 USD off with 2 of 3 uses left, SAVE10 at 10% off with no limit, and an expired 50% code, each row with an active toggle, share, edit and delete icons, and a New code button above

Running a Discount Code Without a POS Upgrade

Ordering & Payments

By menu-MENA Team

Published on August 27, 2026


Why this doesn't touch your POS

A restaurant that wants to run "10% off this weekend" usually hits a wall before the discount reaches anyone: the POS needs a new button, the card machine needs reprogramming, or someone has to explain a workaround to the front-of-house staff at the start of a shift. menu-MENA skips all of that because the order already lives inside the menu. A guest builds a cart and taps Send Order, and it lands in your WhatsApp as a formatted message. A coupon is one more line the platform works out before that message goes anywhere. Nothing to plug in, nothing to reconfigure at the till.

Building a code in the admin panel

Coupons sit on their own page in the sidebar, labeled Promo codes. Tap New code and the form asks for a Code (uppercase letters, digits, - and _, 3 to 32 characters, and it can't be changed once you save it), a Discount type (Percentage or Fixed amount), and a Value. Everything after that is optional: Minimum order, Total uses, Uses per customer, and a Starts / Expires date pair.

The code is the record's own ID in the database, so there's no way to end up with two live coupons sharing a word by accident. Try to reuse SAVE10 while it's still active and the save fails outright instead of quietly overwriting whatever that code was already doing, including how many times it had been redeemed.

A working list might look like this: LASTONE, a flat 25 USD off, capped at 3 total uses and already redeemed twice. SAVE10, 10% off with no cap at all. EXPIRED, 50% off, its Valid column running through to a date that's now passed, sitting with an Expired chip. None of the three needed a second system to set up. All three came from the same New code form.

What the guest actually sees

The Promo code field doesn't show up on every menu. It only appears once a tenant has created at least one coupon, so a restaurant that never touches this feature never shows a guest an empty discount box that does nothing. The switch flips itself: create a first code and the field appears on the public menu automatically, delete the last one and it disappears again.

When a guest reviews an order before sending it, they see a Promo code field with an "Enter a code" placeholder and an Apply button. Type a code and tap Apply, and the platform checks it right away: is it active, has it started, has it expired, is the cart above the minimum. A working code adds a Discount row above the total, worked out before tax, and the field updates to show the actual amount taken off, something like "45 EGP off," even on a percent-based code. A code that doesn't qualify gets a plain reason instead of a generic error: "This code has expired," "Your order is below this code's minimum," or, on a coupon capped per customer, "Add your phone number above to use this code."

That check is rate-limited too: 15 attempts per 5 minutes for a given device and restaurant. Guessing a code by trial and error runs out of tries fast.

The discount only becomes real at the order

Applying a code in the cart is a preview, not a redemption. The actual increment to a coupon's used count happens later, at the moment the order gets written to the database, inside the same transaction. That matters more than it sounds: if two guests are both racing for the last use of a coupon capped at 3, the database re-checks the real count as part of writing each order, so both can't slip through and push the count past the cap. The server also recalculates the discount amount itself rather than trusting whatever the guest's browser sent along, so a stale cart, or a customer who edited their order after applying a code, can't carry a wrong discount into your WhatsApp inbox.

Reading a code's status without opening it

Every row in the Promo codes list carries a status chip: Active, Paused, Expired, Scheduled, or Used up. None of that is stored on the coupon itself. It's worked out live from the fields already set, the active flag, the dates, the use count against the cap, every time the page loads. Flip the switch in a row off and it reads Paused without touching anything else about the code. Let its Expires date pass and it becomes Expired on its own. A code with a future Starts date sits as Scheduled until that day arrives.

A ready-made post to go with the code

The share icon on each row opens a small studio that builds a downloadable image for the code, either a square 1080×1080 post or a 1080×1920 story, with a caption underneath that copies straight into Instagram, Facebook, or a WhatsApp status. The post's language is picked separately from whichever language your dashboard happens to be in, and the image renders in the browser rather than on a server, the same trick WhatsApp ordering relies on elsewhere: Arabic text needs real shaping to read correctly, and the browser already does that work for free.

A tracked code beats telling the cashier to "just knock off 10 percent" for one reason above the rest: it shows up in the numbers afterward, instead of a discount that leaves no trace once the shift ends. Create one, watch its Used column move for a week, and decide from there whether it earns a permanent spot on the menu.

Frequently Asked Questions

No. The discount is calculated inside the order flow that already exists on your menu, the same cart guests use to send an order over WhatsApp. There's nothing to plug into a card terminal or a POS system, and no payment gateway required either. Coupons work whether or not you've turned on Paymob.

Not directly. Uses per customer caps how many times one phone number can redeem a given code, set it to 1 and nobody redeems it twice, but it doesn't distinguish a first-time guest from a regular. Pair it with a low Total uses if you want a welcome code to run out before it becomes common knowledge among returning customers.

The redemption and the order itself get written in the same database transaction, so the used count is re-checked at the exact moment each order is saved. If a code capped at 3 uses already has 3 used orders in flight, a fourth attempt gets rejected as part of that same write, not after the fact.

No. An expired code sits in your Promo codes list with an Expired status chip and stops applying to new orders on its own. Leave it there for the record or delete it, either way it's harmless.

The guest-facing check is rate-limited to 15 attempts per 5 minutes per device and restaurant, and a code that doesn't match the required format (3 to 32 letters, digits, - or _) gets rejected before it even reaches the database. Brute-forcing a short code isn't practical.

No. Coupons are part of the standard plan, 90 EGP/month or 1,000 EGP/year for one branch after the 14-day free trial, no credit card required to start. There's no separate add-on to buy for it.