Overview
In this tutorial, you will set up a common booking workflow:- Send a booking confirmation email after a user completes a booking.
- Send a recovery email if a user starts a booking but does not complete it in time.
- Two Custom Events (
booking_started,booking_complete) - One Journey that branches on completion vs abandonment
- A booking Data Feed for confirmation details
- An optional coupon Data Feed for recovery incentives
Setup flow
- Your app tracks a
booking_startedcustom event. - This enters the user into a Journey.
- The Journey waits for a
booking_completeevent and if not received in time, it sends follow-up reminders. - If the booking completes, OneSignal calls a booking Data Feed at send time and sends a confirmation email with the latest booking details.
- If the booking does not complete within the wait window, the Journey follows the expiration path and sends a recovery email.
Setup
Prerequisites
Before you begin, make sure you have:- A OneSignal app with the Email channel enabled
- A backend endpoint that can return booking and/or coupon data as JSON
- A stable user identifier shared between your app, backend, and OneSignals External ID
- Access to Custom Events
1. Track booking events
Track the following Custom Events. These can be from your app (using our SDK) or from your backend (using our REST API). Event names:booking_started— when the user begins the booking flowbooking_complete— when the booking is successfully completed
- App - Mobile and Web
- Server Side
Use the
trackEvent() method on our Mobile SDK and/or Web SDK to send custom events directly from your app/website.Example
Use the same user identity when tracking events and when returning data from your backend. Mismatched IDs are the most common cause of missing personalization.
2. Create Data Feed aliases
In OneSignal, go to Settings > Data Feeds and create the following aliases. Booking Data Feed: Use this feed to pull the latest booking details at send time.- Alias:
booking_data - Method: GET
- URL:
Example endpoint
JSON
- Alias:
coupon - Method: GET
- URL:
Example endpoint
JSON
3. Create email templates
Booking confirmation email:
Subject:Booking recovery email
Subject:- Using a Coupon Data Feed
- Without a Coupon Data Feed
Always include
default filters in Liquid to prevent blank content if a Data Feed field is missing.4. Build the Journey
- In OneSignal, go to Messages > Journeys > Create Journey
-
Set the Entry Trigger to:
- Custom Event:
booking_started
- Custom Event:
-
Add a Wait Until step:
- Condition: Custom Event occurs
- Event name:
booking_complete - Maximum wait time: 10 minutes
- Enable the expiration path
-
Configure the branches:
- Completed: Send booking confirmation email
- Data Feed:
booking_data
- Data Feed:
- Expired: Send recovery email
- Data Feed:
coupon
- Data Feed:
- Completed: Send booking confirmation email
The expiration branch allows you to handle abandonment without additional logic in your app. See:
- Journey settings - for details on Custom Event entry and exit rules
- Journeys actions - for details on Wait Until steps and expiration branches
5. Test and verify
Verify events
Trigger the custom events from your app or backend and confirm. In OneSignal, go to Analytics > Custom Events and confirm you see:booking_startedevents appear for your External IDbooking_completeevents appear for your External ID
Verify Data Feeds
Manually call your Data Feed endpoints using a known user ID and confirm:- A 200 response is returned
- All expected fields are present
Verify emails
Send test messages from the Journey editor and confirm:- Booking emails contain real booking details
- Recovery emails contain a valid coupon
- No Liquid variables render empty
If personalization is missing, confirm that the user ID in the Data Feed request matches the user who triggered the Journey.
Example: Data Feed implementation
Example Node.js Data Feed endpoints
Example Node.js Data Feed endpoints
This example shows a minimal Express implementation for booking confirmation and recovery Data Feeds. Your backend language, framework, and data source can differ as long as the JSON response shape matches your email templates.
Booking Data Feed example
Coupon Data Feed example
Implementation guidelines
- Keep responses fast (Data Feeds are called at send time)
- Always return a predictable JSON structure
- Use 404 when no data exists
- Secure endpoints with an API key sent via request headers
Common issues
Email shows empty values
- Data Feed returned 404
- Field names changed in the JSON response
- User identity mismatch
Journey does not branch
booking_completeevent not tracked- Event name mismatch (case-sensitive)
- Event occurs outside the wait window
Data Feed returns 401 or 403
- Missing or invalid API key
- Header not configured in the Data Feed settings
Next steps
- Add event properties (service type, price) for more advanced Journey conditions
- Add additional recovery steps such as push or SMS reminders
- Use Journey exit rules to prevent repeated recovery messages