- Triggers Journey entry, or
- Matches a Wait Until condition inside the Journey
How Custom Event personalization works
Add event properties to your Journey messages following these steps:Send a Custom Event with properties
Reference event properties in your Journey message templates
Common Liquid access patterns
Nested Liquid access patterns
You can also access nested properties using dot and bracket notation:Create a Journey
- See Journeys settings for Entry rules.
- See Journeys actions for Wait Until conditions.
Event property storage rules
- You can use multiple events in your Journey by combining entry rules and Wait Until steps.
- Maximum: 100 stored event properties per user per Journey instance (oldest dropped).
- Event properties are stored per user, per Journey instance.
- Events sent before entry are not accessible.
- Event properties are cleared when the user exits the Journey.
Custom Event Liquid reference
Use these objects to access stored events inside the Journey.- If using a Custom Event Entry Rule, than this is the event that caused Journey entry.
- If not using a Custom Event Entry Rule, then this is the first event stored by matching a Wait Until condition.
- If only one event is stored,
first_eventandlast_eventreturn the same thing.
- Replace
EVENT_NAMEwith your event name (e.g.,purchase). - If the same event name is used multiple times, this returns the most recent instance.
"name": "order status"- Use for loops to iterate over them.
journey.first_eventis shorthand forjourney.all_events[0].journey.last_eventis shorthand for the most recent event in the array.
Example: Abandoned cart templates using Custom Events
This example shows how to personalize abandoned cart messages using Custom Events. It builds on the Abandoned Cart tutorial. Example Custom Event set:Email template
This example shows how to build an email template that displays:- The cart item count
- Each product with image, name, quantity, and price using a for-loop
- A button that links to the customer’s unique cart URL

Example Abandoned Cart Email Template
Create the email template
Add the layout structure
- Rows 1, 2, and 4: one column with a Paragraph block
- Row 3: four columns with HTML | Paragraph | Paragraph | Paragraph
- Row 5: one column with a Button block

Starter email template for abandoned cart
Display the item count
Start the for-loop
- Begins a loop that iterates over each object in the
cartarray - Creates a temporary variable
productrepresenting the current item - Everything between
{% for %}and{% endfor %}repeats once per cart item - You can name
productanything (e.g.,item,cartItem)—just stay consistent
Display product details
- Column 2:
{{product.product_name}} - Column 3:
{{product.product_quantity}} - Column 4:
{{product.product_price}}
- On first iteration,
product= first object in cart array {{product.product_image}}gets the first item’s image- On second iteration,
product= second object - Row repeats automatically for all cart items
End the for-loop
{% for %} must have a matching {% endfor %}. Missing this will break email rendering.Add the cart URL button

Finished base email template for abandoned cart without styling
Test the template
- Add the template to a blank Journey and set the entry rule to a Custom Event.
- Enabling the Journey and entering yourself into it via the Custom Event API.
- Verify the data displays correctly.
Push template
Push notifications have limited space, so display one item and mention the total count. Message field: Display item and count with correct grammar using conditional statements.
Abandoned cart push template example
Troubleshooting & best practices
Common mistakes:- Always test templates before going live
- Use default filters for optional properties
- Validate event schema matches template expectations
Related pages
Message personalization
Custom Events
Journeys overview
Journey settings
Wait Until actions
Using Liquid syntax
Templates
support@onesignal.comPlease include:- Details of the issue you’re experiencing and steps to reproduce if available
- Your OneSignal App ID
- The External ID or Subscription ID if applicable
- The URL to the message you tested in the OneSignal Dashboard if applicable
- Any relevant logs or error messages