Store Builder

Flash sales and on-page promotions

Two kinds of flash sale — Shopee-style product deals (sale price, quota, sold bar) and discount codes put in front of shoppers with the voucher list, the countdown and the sale badge.

There are two kinds of flash sale, and they solve different problems:

  • A product flash sale (the Shopee / Lazada kind) — for a window of time a few products sell at a deal price, with a limited quota, and shoppers see the struck price, "−X%" and a "Sold" bar. There is no code to type: the sale price goes straight into the order. See the section just below.
  • A discount-code flash sale — you create a code and put it on the page for shoppers to see and tap. See the second half of this page.

Product flash sale

Created in Manage → Flash sale (vi: Quản lý → Flash sale), next to Discounts. A campaign has a name, a Starts at and Ends at time, an Active switch, and a list of Items. For each product (or each variant — leave it on All variants when every variant gets the same price) you fill in:

  • Sale price — has to be lower than the base price. The screen shows the base price and the percentage beside it so you can check. A "flash sale" that costs more than the normal price is a typing mistake, so the server refuses to save it.
  • Quota — how many units sell at the sale price across the whole campaign. 0 means unlimited.
  • Per-order limit — how many units one order may buy at the sale price. 0 means unlimited.

The status follows the clock by itself: Scheduled, Running, Ended, or Off while the campaign is not active. When time runs out or the quota is used up, the product goes back to its base price on its own — you never take anything down by hand.

Buying past the limit

The shopper is not stopped. The units within the limit are charged the sale price, the rest the base price, and the order records them as two lines so you can see which is which. With a per-order limit of 2, a shopper buying 3 pays the sale price for 2 and the base price for 1. The remaining quota splits the same way — with 1 unit left, a shopper buying 2 gets 1 at the sale price and 1 at the base price.

The quota is only taken when the order is placed, not when something goes into the cart. When two shoppers race for the last unit, only one gets it; the other is told the price has just changed and sees the new total before ordering again — the page never quietly charges more than the figure the shopper was just shown. When an order is cancelled, its units go back to the campaign.

Stacking a discount code

Your choice, per campaign:

Allow discount codes — Let a shopper stack a discount code on top of the sale price.

It is off by default: the sale price is already the discount, and a code on top of it can mean selling at a loss. While it is off, a code still works on the other products in the order — only the units charged at the sale price are not reduced further. A code's minimum order still counts the whole order.

One product (or variant) cannot sit in two active campaigns whose times overlap — the screen names the other campaign so you can fix it.

Showing the flash sale on a page

Two elements in the Product group of the element panel, for a product card or a product page:

Element vi What it does
Flash sale price Giá flash sale Shows the normal price; while the product is on flash sale it switches to the sale price, strikes the base price and shows −X%
Flash sale progress Tiến độ flash sale Hidden until the product is on flash sale; then shows a sold / quota bar, a message and a small countdown

Use Flash sale price instead of Price display on product cards. It shows the normal price when nothing is on sale, so you do not have to change the page when the campaign ends.

The progress message has three steps, all editable in its settings: "Sold" with the count, "Almost gone" once 80% of the quota is sold, and "Sold out". A product with an unlimited quota gets no bar, only the sold count.

Both elements read their figures when the shopper opens the page and switch exactly at the end time by the server's clock, so the "Sold" count is always current — there is no need to republish the page when you edit a campaign.

The "flash sale now" block

The quickest way: drag out the Flash sale price row and pick its second card — a whole block with a heading, a countdown and a product grid, every card already carrying the flash sale price, the progress bar and an add-to-cart button.

If you build it yourself, two things to know:

  • Product list has a Running flash sale source — the grid shows exactly the products on sale right now. With no campaign running, the list shows its own empty state.
  • Countdown has a Flash sale source — it counts to the running campaign's end, and follows when you move or extend that end time.

The trap

In the cart drawer, a product line wholly inside the quota shows the sale price. But a line that is partly at the sale price and partly at the base price — the shopper bought past the per-order limit, or only part of the quota was left — shows the base unit price, because no single unit price tells the truth about that line. The subtotal and what the shopper actually pays still count each part correctly, so the final figure is always at or below what that line suggests, never above it.

Discount-code flash sale

A flash sale on a page usually needs four things: the shopper sees the code, sees how long is left, taps to use the code, and sees the lower price before ordering. Each is its own element on the element panel:

Element vi Group
Voucher list Danh sách mã giảm giá Storefront (Gian hàng)
Countdown Đếm ngược Storefront (Gian hàng)
Sale badge Nhãn khuyến mãi Product (Sản phẩm)
Discount code box Ô mã giảm giá Form builder → Basic

The codes themselves are still created in Manage → Discounts — see Discount codes. The elements here only show a code; whether it is actually taken off an order is still decided there.

First step: list the code publicly

The voucher list and the countdown see no codes on their own. Open the code in Manage → Discounts and switch on:

List publicly — Shown on your storefront's public voucher list — anyone who opens the shop can see this code.

It is off by default, on purpose: a code you sent privately by email or to one influencer stops being private the moment it appears on your home page. Only the codes you switch on by hand ever go out.

Two kinds of code cannot be switched on, and the screen says why:

  • Single-use codes — the first person who sees it would spend it before anyone else could.
  • Codes limited to specific members — turn that limit off first if you want to list the code publicly.

A code shows on the page while it is running: Active is on, its Starts at date has arrived and its Ends at date has not passed. A Scheduled code does not show yet, and an Expired one disappears on its own — you do not have to take it down by hand when the sale ends.

Voucher list

Each public code is a card: the code, its internal title, what it saves ("20% off"), any minimum-order condition, and an Apply button. The list is fetched when the shopper opens the page, so a code you have just listed shows on the next load — there is no need to republish the page.

What a tap on a card's Apply does depends on the page:

  • The page has a Discount code box (anywhere on the page, not necessarily next to the list): the code is filled into that box and the price updates at once, exactly as if the shopper had typed it.
  • The page has no such box: the code is copied to the clipboard, and the card says so. The shopper pastes it at checkout later.

So the best way to build a flash-sale landing page is to put the voucher list on the same page as the order form — one tap and the shopper is done.

With no public codes the list shows the empty line you set in the Messages group — word it as "nothing right now", not as an error.

Countdown

Four boxes — Days / Hours / Minutes / Seconds — ticking every second. For a product flash sale, switch on the Flash sale source (see above). For a code, there are two ways to tell it what to count down to, in the Content group:

Ends — the countdown's target. Linked code — when it names a published voucher with an end time, that voucher's end time is used instead.

Use Linked code for a flash sale. When you move or extend the code's end date in Manage → Discounts, the countdown follows; without it you have to remember to change both the page and the code, and one day you will not — the clock says "2 hours left" while the code has already expired.

Still fill in Ends, because it is the safety net: if the linked code is mistyped, is not listed publicly, or has no end date, the countdown counts to this instead of showing something wrong.

The countdown runs on the server's clock, not the shopper's device. Setting a phone's clock back does not make the sale "last longer". In the instant before the page has loaded, the boxes are blank rather than 00 — showing 00:00:00 would read as "already over" before anything has run.

At zero the countdown stops and shows the line from the Messages group ("Chương trình đã kết thúc" by default — change it for an English store).

What the countdown does not do: it does not end the promotion. The code stops working because of its own Ends at date — the server refuses an expired code at order time, whatever the page shows. Nor does the countdown hide its section or change product prices when it reaches zero.

The digit size, the gap, the corner radius and the two box colours are in the Boxes group, and can be set per screen size.

Sale badge

A small "−20%" or "Sale" pill on a product card or product page. The percentage is computed from the product's price and its compare-at price — you do not type it.

A product with no compare-at price, or one no higher than the price, shows nothing at all — the badge never invents a discount. If a badge is missing, check that product's compare-at price first.

The badge follows the product's price, not your discount codes: a FLASH20 code does not make the badge say "−20%".

The discount code box and the updated price

The discount code box has to sit inside an order form — see Forms. When the shopper presses Apply beside the box, or taps a card in the voucher list, the line under the box shows one of four sentences you write: applied, unknown code, code not usable on this order, or could not check just now (a network problem — that one must not blame the shopper's code).

The trap: the price updates before submitting only when the form orders the whole cart and the cart has something in it. On a form that orders one fixed product (the landing-page kind), pressing Apply currently shows nothing — the code is still really checked when the shopper presses Submit, and a bad code stops the order, but the shopper does not see the lower price first.

Updated 25/09/2026