Build an automated flash sale campaign that drives conversions during a time-limited promotion, from a simple time-based flow to a fully personalized Journey with VIP early access and buyer suppression.
This tutorial walks through a complete flash sale Journey using Black Friday as the running example (40% off sitewide, midnight to midnight). The pattern applies to any time-limited promotion.
Case 1 – Basic: Pure time-based, no tags. Everyone receives the same messages at scheduled times. Good for your first flash sale or teams without tag infrastructure.
Case 2 – Advanced: Uses tags (vip_customer, wishlist_count, last_purchase_date) for VIP early access, wishlist personalization, and buyer suppression. Start with Case 1 and layer in Case 2 targeting as your data matures.
These templates are starting points: clone, edit, and re-use them in your own Journey. They use Liquid syntax for personalization.
Push Notification templates
Email templates
In-App Message templates
When
Name
Title
Message
Day before sale
Sale tomorrow
🛍️ Tomorrow only. 40% off sitewide.
Your Black Friday sale starts at midnight tonight. Don’t miss it.
Mid-sale
Mid-sale nudge
⏰ Still going, 40% off ends tonight
The Black Friday sale is still live. Don’t leave your items behind.
2 hours before close
Last chance
🔥 2 hours left, last chance
The Black Friday sale closes at midnight. This is your last chance.
Sale launch, VIPs (Case 2)
VIP early access
🎉 You’re in early, {{first_name}}
VIP early access is live. 40% off everything, shop before everyone else.
Sale launch + 1 hour (Case 2)
Sale launch
🛍️ Black Friday is LIVE
40% off sitewide, ends tonight at midnight. Shop now.
Sale launch, wishlist users (Case 2)
Wishlist on sale
💜 Your saved items are 40% off
You have {{user.tags.wishlist_count}} items on your wishlist. They’re all on sale right now.
Templates
Create and manage reusable message templates.
Message personalization
Overview of all personalization options available in OneSignal.
Emails carry the long-form moments of the Journey. Three emails fire: pre-sale excitement, sale launch, and a halfway reminder.Pre-sale excitement (2 days before)Purpose: Build anticipation and drive wishlist adds before the sale opens.Suggested subject: Black Friday is almost here 🛍️Content outline:
A teaser of what’s coming (40% off everything)
Preview of featured products or categories
CTA to browse and add items to wishlist
Countdown to sale start
Sale is live (sale day)Purpose: Announce the sale launch and drive immediate traffic.Suggested subject: Black Friday is LIVE, 40% off everythingContent outline:
Bold announcement that the sale has started
Featured deals and product highlights
Clear CTA to shop now
Sale end time prominently displayed
Final reminder (halfway through sale)Purpose: Recover users who haven’t purchased yet.Suggested subject: Don’t miss out, sale ends tonightContent outline:
Reminder that time is running out
Highlight top-selling or low-stock items
Urgency messaging with countdown
CTA to complete purchase
Email messaging
Create and send email campaigns.
Message personalization
Overview of all personalization options available in OneSignal.
In-app messages fire when users open your app. Two are included: a pre-sale teaser and a sale-day banner.Pre-sale excitement (2 days before)Use a banner or modal to build anticipation:
Headline: “Black Friday is coming!”
Body: “40% off everything starts Friday at midnight. Add items to your wishlist now.”
CTA: Deep link to wishlist or sale preview page
Sale is live banner (sale day)Show a banner when users open the app during the sale:
This Journey runs entirely on time-based Wait nodes. No tags, no targeting. Everyone receives the same messages at scheduled times. Set it live 2 days before the sale opens.
Email + In-App Message: Pre-sale excitement (2 days before)
Goal: Build anticipation a few days before the sale.Add an Email node as the first step, then an In-App Message node immediately after.The email lands when the user enters the Journey. The IAM is queued and displays the next time they open your app.
2
Wait: 1 day
Goal: Advance to the day before the sale.Add a Wait node set to 1 day.
3
Push Notification: Sale starts tomorrow (day before)
Goal: Reminder the day before.Add a Push Notification node.
Field
Value
Title
Tomorrow only. 40% off sitewide.
Body
Your Black Friday sale starts at midnight tonight. Don't miss it.
Launch URL
Your sale landing page
4
Wait: 1 day
Goal: Advance to sale day.Add a Wait node set to 1 day.
5
Email + In-App Message: Sale is live (sale day)
Goal: Announce the sale launch.Add an Email node, then an In-App Message node.The email announces the sale is live. The IAM displays a sale banner when users open the app.
6
Wait: a few hours
Goal: Give users time to see the launch messages before the mid-sale nudge.Add a Wait node set to 3–4 hours (adjust based on your sale duration).
7
Push Notification: Mid-sale nudge
Goal: Re-engage users who haven’t visited yet.Add a Push Notification node.
Field
Value
Title
Still going, 40% off ends tonight
Body
The Black Friday sale is still live. Don't leave your items behind.
Launch URL
Your sale page
8
Wait: until halfway through sale
Goal: Advance to the halfway point.Add a Wait node. For a 24-hour sale that started at midnight, set this to 6–8 hours to land around midday/afternoon.
9
Email: Final reminder
Goal: Last email push to recover non-purchasers.Add an Email node with urgency messaging and countdown.
10
Wait: until 2 hours before end
Goal: Advance to the final urgency window.Add a Wait node to land 2 hours before the sale ends. For a midnight-to-midnight sale, this is around 10 PM.
11
Push Notification: Last chance
Goal: Final urgency push.Add a Push Notification node.
Field
Value
Title
2 hours left, last chance
Body
The Black Friday sale closes at midnight. This is your last chance.
Time of the user’s most recent purchase, stored as a Unix timestamp in seconds (10 digits)
These tags must be maintained by your backend and synced to OneSignal. See Tags for setup.
The time elapsed greater than operator compares the current time to a Unix timestamp stored on the tag. Store last_purchase_date as a Unix timestamp in seconds (10 digits), not milliseconds or a formatted date. See Tags: Time Operators for details.
Case 2 follows the same overall timing as Case 1, but adds a VIP branch at launch, a wishlist branch right after, and a buyer-suppression filter on every urgency message.
1
Email + In-App Message: Pre-sale excitement (2 days before)
Goal: Build anticipation a few days before the sale.Add an Email node as the first step, then an In-App Message node immediately after.The email lands when the user enters the Journey. The IAM is queued and displays the next time they open your app.
2
Wait: 1 day
Goal: Advance to the day before the sale.Add a Wait node set to 1 day.
3
Push Notification: Sale starts tomorrow (day before)
Goal: Reminder the day before.Add a Push Notification node.
Field
Value
Title
Tomorrow only. 40% off sitewide.
Body
Your Black Friday sale starts at midnight tonight. Don't miss it.
Launch URL
Your sale landing page
4
Wait: 1 day
Goal: Advance to sale day.Add a Wait node set to 1 day.
5
Branch: VIP / General split (sale launch)
Goal: Give VIPs a 1-hour head start.Add a Yes/No Branch node:
Condition:User Tagvip_customer · operator is · value true
Yes branch (VIP): Add a Push Notification node immediately:
Field
Value
Title
You're in early, {{first_name}} 🎉
Body
VIP early access is live. 40% off everything, shop before everyone else.
Launch URL
Your sale page
No branch (general): Add a Wait node set to 1 hour, then a Push Notification node:
Field
Value
Title
Black Friday is LIVE 🛍️
Body
40% off sitewide, ends tonight at midnight. Shop now.
Launch URL
Your sale page
6
Email + In-App Message: Sale is live
Goal: Announce the sale to everyone.Connect both branches into the same next node. Add an Email node, then an In-App Message node. The email announces the sale is live and the IAM displays a sale banner when users open the app.
7
Branch: Wishlist personalization
Goal: Send a personalized push to wishlist users.Add a Yes/No Branch node:
Condition:User Tagwishlist_count · operator greater than · value 0
Yes branch (wishlist users): Add a Push Notification node:
Field
Value
Title
Your saved items are 40% off
Body
You have {{user.tags.wishlist_count}} items on your wishlist. They're all on sale right now.
Launch URL
Your wishlist page
No branch (no wishlist): Continue with no message.Connect both branches into the next step.
8
Wait: a few hours
Goal: Give users time before the mid-sale nudge.Add a Wait node set to 3–4 hours.
9
Branch + Push: Mid-sale nudge (buyer suppression)
Goal: Nudge non-buyers only.Add a Yes/No Branch node. Match any of these filters:
User Taglast_purchase_date · operator time elapsed greater than · value 4 hours
User Taglast_purchase_date · operator does not exist
Adjust the 4 hours value based on how long after sale launch this step fires in your Journey.Yes branch (non-buyers): Add a Push Notification node:
Field
Value
Title
Still going, 40% off ends tonight
Body
The Black Friday sale is still live. Don't leave your items behind.
Launch URL
Your sale page
No branch (buyers): Skip the push, route directly to the next step.
10
Wait: until halfway through sale
Add a Wait node to reach the halfway point.
11
Branch + Email: Final reminder (buyer suppression)
Goal: Email non-buyers only.Add a Yes/No Branch node. Match any of these filters:
User Taglast_purchase_date · operator time elapsed greater than · value 12 hours (halfway through a 24-hour sale)
User Taglast_purchase_date · operator does not exist
Yes branch (non-buyers): Add an Email node with urgency messaging.No branch (buyers): Skip the email.
12
Wait: until 2 hours before end
Add a Wait node to reach the final urgency window.
13
Branch + Push: Last chance (buyer suppression)
Goal: Final push to non-buyers only.Add a Yes/No Branch node. Match any of these filters:
User Taglast_purchase_date · operator time elapsed greater than · value 22 hours (two hours before a midnight close)
User Taglast_purchase_date · operator does not exist
Yes branch (non-buyers): Add a Push Notification node:
Field
Value
Title
2 hours left, last chance
Body
The Black Friday sale closes at midnight. This is your last chance.
Launch URL
Your sale page or cart
No branch (buyers): End of Journey.
The last_purchase_date filter only suppresses buyers if your backend updates the tag in near-real-time. If your stack updates the tag nightly, buyers in the early hours of the sale will still receive urgency messages later that day. Verify the sync cadence before launch.
Apply buyer suppression to every urgency message. Without it, users who bought early still receive “last chance” pushes, which is the most common cause of unsubscribes after a flash sale.
Verify tag freshness before launch by simulating a purchase and confirming the last_purchase_date tag updates within minutes.
All Case 1 best practices still apply. Quiet hours, deep linking, and pausing the Journey if the sale ends early.
Be aware of message volume. A VIP wishlist user who never buys can receive up to 4 pushes and 3 emails across the full sequence. Make sure that volume feels appropriate for your audience before launch.
Start with Case 1 if you’re running your first flash sale or don’t have tag infrastructure in place. As you add tags to your data layer, upgrade to Case 2 by adding the VIP branch, wishlist branch, and buyer-suppression filters. The VIP early access alone is worth the effort: it rewards your best customers and creates social proof when they share their finds.After this Journey is live, consider adding SMS for the final urgency push (see SMS messaging) or extending the pattern to other time-limited promotions like summer sales, anniversary events, or new product launches.