- 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.
At a glance
Setup is the same for both cases. The only difference is how targeting and branching are applied.- Define the entry segment.
- Build the push, email, and in-app message templates.
- Configure Journey entry, exit, and re-entry rules.
- Wire up the Journey steps:
- Case 1: Linear flow with Wait nodes, everyone gets the same messages.
- Case 2: Add VIP branch, wishlist branch, and buyer suppression.
Campaign goals
| Goal | How this campaign achieves it |
|---|---|
| Build pre-sale anticipation | Email + in-app message before the sale |
| Remind users the day before | Push the day before to keep the sale top of mind |
| Announce the sale launch | Email + in-app message when the sale goes live |
| Re-engage mid-sale | Push a few hours after launch for non-visitors |
| Final email reminder | Email halfway through to recover non-purchasers |
| Last-chance urgency | Push 2 hours before the sale ends |
| Personalize and protect trust (Case 2) | VIP early access, wishlist push, and buyer suppression via tags |
Prerequisites
- A OneSignal account with push notifications set up for your app or site
- Push permission enabled for your users
- Familiarity with Journeys concepts (entry/exit rules, message and action steps, etc.)
- Email channel set up if you want to send emails (see Email setup)
- In-app messaging enabled if you want to show banners during the sale window (see In-app messages setup)
Segments
Entry segment (both cases):- Name: “Total Subscriptions”
- Built-in, no setup needed. All push-subscribed users enter the Journey.
- Name: “VIP Customers”
- Filter: User Tag
vip_customer· operator is · valuetrue
- Name: “Wishlist Users”
- Filter: User Tag
wishlist_count· operator greater than · value0
Templates
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
Message personalization
Journey configuration
Both cases share the same Journey settings. Define them once and use them for either case.Journey settings
| Setting | Value |
|---|---|
| Entry | Audience Segment: “Total Subscriptions” |
| Exit | User reaches the end of the flow |
| Re-entry | No, users receive this Journey only once per sale |
Case 1: Basic time-based Journey
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.Journey timing
The campaign progresses through anticipation (2 days before through the day before), launch (sale day), and urgency (afternoon through close):| Step | When | Channel | Purpose |
|---|---|---|---|
| 1 | 2 days before sale (on entry) | Email + IAM | Build excitement |
| 2 | Day before sale | Push | Sale starts tomorrow |
| 3 | Sale launch | Email + IAM | Sale is live |
| 4 | A few hours after launch | Push | Mid-sale nudge |
| 5 | Halfway through sale | Final email reminder | |
| 6 | 2 hours before close | Push | Last chance |
Basic Journey steps
Email + In-App Message: Pre-sale excitement (2 days before)
Push Notification: Sale starts tomorrow (day before)
| 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 |
Email + In-App Message: Sale is live (sale day)
Wait: a few hours
Push Notification: Mid-sale nudge
| 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 |
Wait: until halfway through sale
Email: Final reminder
Wait: until 2 hours before end
Best practices for Case 1
- Set the Journey live 2 days before the sale. The pre-sale email fires immediately for users who enter.
- Respect quiet hours. Avoid sending pushes between 10 PM and 7 AM in the user’s timezone. Adjust Wait nodes if needed.
- Pause the Journey if the sale ends early. From the dashboard, pause stops remaining Wait nodes and prevents any remaining messages from firing.
- Deep-link every message to the right page. Tapping a push should land users on the sale page, not the app home.
Case 2: Advanced tag-based Journey
Case 2 builds on Case 1 by adding targeting with tags. The timing is the same, but you add:- VIP early access: VIPs get a 1-hour head start at sale launch
- Wishlist personalization: Users with wishlist items get a personalized push
- Buyer suppression: Filter out buyers from urgency messages
Required tags
| Tag | Type | Description |
|---|---|---|
vip_customer | Boolean | true if the user is a VIP customer |
wishlist_count | Number | Count of items in the user’s wishlist |
last_purchase_date | Unix timestamp (seconds) | Time of the user’s most recent purchase, stored as a Unix timestamp in seconds (10 digits) |
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.Advanced Journey steps
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.Email + In-App Message: Pre-sale excitement (2 days before)
Push Notification: Sale starts tomorrow (day before)
| 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 |
Branch: VIP / General split (sale launch)
- Condition: User Tag
vip_customer· operator is · valuetrue
| 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 |
| Field | Value |
|---|---|
| Title | Black Friday is LIVE 🛍️ |
| Body | 40% off sitewide, ends tonight at midnight. Shop now. |
| Launch URL | Your sale page |
Email + In-App Message: Sale is live
Branch: Wishlist personalization
- Condition: User Tag
wishlist_count· operator greater than · value0
| 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 |
Branch + Push: Mid-sale nudge (buyer suppression)
- User Tag
last_purchase_date· operator time elapsed greater than · value4 hours - User Tag
last_purchase_date· operator does not exist
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 |
Branch + Email: Final reminder (buyer suppression)
- User Tag
last_purchase_date· operator time elapsed greater than · value12 hours(halfway through a 24-hour sale) - User Tag
last_purchase_date· operator does not exist
Branch + Push: Last chance (buyer suppression)
- User Tag
last_purchase_date· operator time elapsed greater than · value22 hours(two hours before a midnight close) - User Tag
last_purchase_date· operator does not exist
| 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 |
Best practices for Case 2
- 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_datetag 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.
Compare Case 1 and Case 2
Both cases share the same entry segment, Journey settings, and templates. Case 2 adds targeting.| Case 1: Basic | Case 2: Advanced | |
|---|---|---|
| Data required | None | Tags: vip_customer, wishlist_count, last_purchase_date |
| Setup effort | Low, no tag infrastructure needed | Medium, requires backend tag sync |
| VIP early access | No, everyone gets sale launch at same time | Yes, VIPs get 1-hour head start |
| Wishlist personalization | No | Yes, “your saved items are on sale” push |
| Buyer suppression | No, everyone gets urgency messages | Yes, filter out buyers via last_purchase_date |
| Best for | First flash sale, no tag infrastructure | Teams with existing tags, better UX |